Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/Badge.h>
30#include <AK/Function.h>
31#include <AK/HashMap.h>
32#include <AK/NonnullOwnPtrVector.h>
33#include <AK/OwnPtr.h>
34#include <AK/RefPtr.h>
35#include <AK/String.h>
36#include <Kernel/FileSystem/FileSystem.h>
37#include <Kernel/FileSystem/InodeIdentifier.h>
38#include <Kernel/FileSystem/InodeMetadata.h>
39#include <Kernel/KResult.h>
40
41namespace Kernel {
42
43#define O_RDONLY (1 << 0)
44#define O_WRONLY (1 << 1)
45#define O_RDWR (O_RDONLY | O_WRONLY)
46#define O_ACCMODE (O_RDONLY | O_WRONLY)
47#define O_EXEC (1 << 2)
48#define O_CREAT (1 << 3)
49#define O_EXCL (1 << 4)
50#define O_NOCTTY (1 << 5)
51#define O_TRUNC (1 << 6)
52#define O_APPEND (1 << 7)
53#define O_NONBLOCK (1 << 8)
54#define O_DIRECTORY (1 << 9)
55#define O_NOFOLLOW (1 << 10)
56#define O_CLOEXEC (1 << 11)
57#define O_DIRECT (1 << 12)
58
59// Kernel internal options
60#define O_NOFOLLOW_NOERROR (1 << 29)
61#define O_UNLINK_INTERNAL (1 << 30)
62
63#define MS_NODEV 1
64#define MS_NOEXEC 2
65#define MS_NOSUID 4
66#define MS_BIND 8
67
68class Custody;
69class Device;
70class FileDescription;
71class UnveiledPath;
72
73struct UidAndGid {
74 uid_t uid;
75 gid_t gid;
76};
77
78class VFS {
79 AK_MAKE_ETERNAL
80public:
81 class Mount {
82 public:
83 Mount(FS&, Custody* host_custody, int flags);
84 Mount(Inode& source, Custody& host_custody, int flags);
85
86 InodeIdentifier host() const;
87 InodeIdentifier guest() const { return m_guest; }
88
89 const FS& guest_fs() const { return *m_guest_fs; }
90
91 String absolute_path() const;
92
93 int flags() const { return m_flags; }
94
95 private:
96 InodeIdentifier m_host;
97 InodeIdentifier m_guest;
98 NonnullRefPtr<FS> m_guest_fs;
99 RefPtr<Custody> m_host_custody;
100 int m_flags;
101 };
102
103 static VFS& the();
104
105 VFS();
106 ~VFS();
107
108 bool mount_root(FS&);
109 KResult mount(FS&, Custody& mount_point, int flags);
110 KResult bind_mount(Custody& source, Custody& mount_point, int flags);
111 KResult unmount(InodeIdentifier guest_inode_id);
112
113 KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
114 KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> = {});
115 KResult mkdir(StringView path, mode_t mode, Custody& base);
116 KResult link(StringView old_path, StringView new_path, Custody& base);
117 KResult unlink(StringView path, Custody& base);
118 KResult symlink(StringView target, StringView linkpath, Custody& base);
119 KResult rmdir(StringView path, Custody& base);
120 KResult chmod(StringView path, mode_t, Custody& base);
121 KResult chmod(Inode&, mode_t);
122 KResult chown(StringView path, uid_t, gid_t, Custody& base);
123 KResult chown(Inode&, uid_t, gid_t);
124 KResult access(StringView path, int mode, Custody& base);
125 KResultOr<InodeMetadata> lookup_metadata(StringView path, Custody& base, int options = 0);
126 KResult utime(StringView path, Custody& base, time_t atime, time_t mtime);
127 KResult rename(StringView oldpath, StringView newpath, Custody& base);
128 KResult mknod(StringView path, mode_t, dev_t, Custody& base);
129 KResultOr<NonnullRefPtr<Custody>> open_directory(StringView path, Custody& base);
130
131 size_t mount_count() const { return m_mounts.size(); }
132 void for_each_mount(Function<void(const Mount&)>) const;
133
134 InodeIdentifier root_inode_id() const;
135
136 void sync();
137
138 Custody& root_custody();
139 KResultOr<NonnullRefPtr<Custody>> resolve_path(StringView path, Custody& base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
140 KResultOr<NonnullRefPtr<Custody>> resolve_path_without_veil(StringView path, Custody& base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
141
142private:
143 friend class FileDescription;
144
145 const UnveiledPath* find_matching_unveiled_path(StringView path);
146 KResult validate_path_against_process_veil(StringView path, int options);
147
148 RefPtr<Inode> get_inode(InodeIdentifier);
149
150 bool is_vfs_root(InodeIdentifier) const;
151
152 void traverse_directory_inode(Inode&, Function<bool(const FS::DirectoryEntry&)>);
153
154 Mount* find_mount_for_host(InodeIdentifier);
155 Mount* find_mount_for_guest(InodeIdentifier);
156
157 Lock m_lock { "VFSLock" };
158
159 RefPtr<Inode> m_root_inode;
160 Vector<Mount> m_mounts;
161
162 RefPtr<Custody> m_root_custody;
163};
164
165}