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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/Span.h>
#include <AK/Time.h>
#include <Kernel/FileSystem/DeviceFileTypes.h>
#include <Kernel/FileSystem/InodeIdentifier.h>
#include <Kernel/Forward.h>
#include <Kernel/UnixTypes.h>
namespace Kernel {
class Process;
constexpr u64 encoded_device(MajorNumber major, MinorNumber minor)
{
return (minor.value() & 0xff) | (major.value() << 8) | ((minor.value() & ~0xff) << 12);
}
static inline MajorNumber major_from_encoded_device(dev_t dev) { return (dev & 0xfff00u) >> 8u; }
static inline MinorNumber minor_from_encoded_device(dev_t dev) { return (dev & 0xffu) | ((dev >> 12u) & 0xfff00u); }
inline bool is_directory(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; }
inline bool is_character_device(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; }
inline bool is_block_device(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; }
inline bool is_regular_file(mode_t mode) { return (mode & S_IFMT) == S_IFREG; }
inline bool is_fifo(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; }
inline bool is_symlink(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; }
inline bool is_socket(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; }
inline bool is_sticky(mode_t mode) { return (mode & S_ISVTX) == S_ISVTX; }
inline bool is_setuid(mode_t mode) { return (mode & S_ISUID) == S_ISUID; }
inline bool is_setgid(mode_t mode) { return (mode & S_ISGID) == S_ISGID; }
enum class UseEffectiveIDs {
Yes,
No
};
struct InodeMetadata {
bool is_valid() const { return inode.is_valid(); }
bool may_read(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const;
bool may_write(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const;
bool may_execute(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const;
bool may_read(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const
{
if (u == 0)
return true;
if (uid == u)
return (mode & S_IRUSR) == S_IRUSR;
if (gid == g || eg.contains_slow(gid))
return (mode & S_IRGRP) == S_IRGRP;
return (mode & S_IROTH) == S_IROTH;
}
bool may_write(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const
{
if (u == 0)
return true;
if (uid == u)
return (mode & S_IWUSR) == S_IWUSR;
if (gid == g || eg.contains_slow(gid))
return (mode & S_IWGRP) == S_IWGRP;
return (mode & S_IWOTH) == S_IWOTH;
}
bool may_execute(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const
{
if (u == 0)
return true;
if (uid == u)
return (mode & S_IXUSR) == S_IXUSR;
if (gid == g || eg.contains_slow(gid))
return (mode & S_IXGRP) == S_IXGRP;
return (mode & S_IXOTH) == S_IXOTH;
}
bool is_directory() const { return Kernel::is_directory(mode); }
bool is_character_device() const { return Kernel::is_character_device(mode); }
bool is_block_device() const { return Kernel::is_block_device(mode); }
bool is_device() const { return is_character_device() || is_block_device(); }
bool is_regular_file() const { return Kernel::is_regular_file(mode); }
bool is_fifo() const { return Kernel::is_fifo(mode); }
bool is_symlink() const { return Kernel::is_symlink(mode); }
bool is_socket() const { return Kernel::is_socket(mode); }
bool is_sticky() const { return Kernel::is_sticky(mode); }
bool is_setuid() const { return Kernel::is_setuid(mode); }
bool is_setgid() const { return Kernel::is_setgid(mode); }
ErrorOr<struct stat> stat() const
{
if (!is_valid())
return EIO;
struct stat buffer = {};
buffer.st_rdev = encoded_device(major_device, minor_device);
buffer.st_ino = inode.index().value();
buffer.st_mode = mode;
buffer.st_nlink = link_count;
buffer.st_uid = uid.value();
buffer.st_gid = gid.value();
buffer.st_dev = 0; // FIXME
buffer.st_size = size;
buffer.st_blksize = block_size;
buffer.st_blocks = block_count;
buffer.st_atim = atime.to_timespec();
buffer.st_mtim = mtime.to_timespec();
buffer.st_ctim = ctime.to_timespec();
return buffer;
}
InodeIdentifier inode;
off_t size { 0 };
mode_t mode { 0 };
UserID uid { 0 };
GroupID gid { 0 };
nlink_t link_count { 0 };
Time atime {};
Time ctime {};
Time mtime {};
Time dtime {};
blkcnt_t block_count { 0 };
blksize_t block_size { 0 };
MajorNumber major_device { 0 };
MinorNumber minor_device { 0 };
};
}
|