summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibIPC/File.h
blob: be5a50cda33da0c22d1b355e75048a7bd4948a2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Noncopyable.h>
#include <AK/StdLibExtras.h>
#include <unistd.h>

namespace IPC {

class File {
    AK_MAKE_NONCOPYABLE(File);

public:
    // Must have a default constructor, because LibIPC
    // default-constructs arguments prior to decoding them.
    File() = default;

    // Intentionally not `explicit`.
    File(int fd)
        : m_fd(fd)
    {
    }

    // Tagged constructor for fd's that should be closed on destruction unless take_fd() is called.
    // Note that the tags are the same, this is intentional to allow expressive invocation.
    enum Tag {
        ConstructWithReceivedFileDescriptor = 1,
        CloseAfterSending = 1,
    };
    File(int fd, Tag)
        : m_fd(fd)
        , m_close_on_destruction(true)
    {
    }

    File(File&& other)
        : m_fd(exchange(other.m_fd, -1))
        , m_close_on_destruction(exchange(other.m_close_on_destruction, false))
    {
    }

    File& operator=(File&& other)
    {
        if (this != &other) {
            m_fd = exchange(other.m_fd, -1);
            m_close_on_destruction = exchange(other.m_close_on_destruction, false);
        }
        return *this;
    }

    ~File()
    {
        if (m_close_on_destruction && m_fd != -1)
            close(m_fd);
    }

    int fd() const { return m_fd; }

    // NOTE: This is 'const' since generated IPC messages expose all parameters by const reference.
    [[nodiscard]] int take_fd() const
    {
        return exchange(m_fd, -1);
    }

private:
    mutable int m_fd { -1 };
    bool m_close_on_destruction { false };
};

}