The Pedigree Project 0.1
file-metadata.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "file-metadata.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/syscallError.h"
5
6#include "DevFs-block.h"
7#include "DevFs.h"
8#include "logging.h"
9#include "modules/system/console/Console.h"
10#include "modules/system/vfs/File.h"
11#include "modules/system/vfs/VFS.h"
12#include "user-namespace.h"
13#include <sys/stat.h>
14
15bool posix_stat_file(const char* name, File* pFile, struct stat* st) {
16 static ConstantString nullName = MakeConstantString("null");
17 int mode = 0;
19 if (pFile->isCharacterDevice() ||
20 (pFile->getFilesystem() == g_pDevFs && pFile->getName() == nullName)) {
21 F_NOTICE(" -> S_IFCHR");
22 mode = S_IFCHR;
23 } else if (pFile->isBlockDevice()) {
24 mode = S_IFBLK;
25 } else if (pFile->isDirectory()) {
26 F_NOTICE(" -> S_IFDIR");
27 mode = S_IFDIR;
28 } else if (pFile->isSymlink()) {
29 F_NOTICE(" -> S_IFLNK");
30 mode = S_IFLNK;
31 } else if (pFile->isPipe() || pFile->isFifo()) {
32 F_NOTICE(" -> S_FIFO");
33 mode = S_IFIFO;
34 } else if (pFile->isSocket()) {
35 F_NOTICE(" -> S_SOCK");
36 mode = S_IFSOCK;
37 } else {
38 F_NOTICE(" -> S_IFREG");
39 mode = S_IFREG;
40 }
41
42 // Clear any cruft in the stat structure before we fill it.
43 ByteSet(st, 0, sizeof(*st));
44
45 const File::Attributes attributes = pFile->getAttributes();
46 uint32_t permissions = attributes.permissions;
47 if (permissions & FILE_UR)
48 mode |= S_IRUSR;
49 if (permissions & FILE_UW)
50 mode |= S_IWUSR;
51 if (permissions & FILE_UX)
52 mode |= S_IXUSR;
53 if (permissions & FILE_GR)
54 mode |= S_IRGRP;
55 if (permissions & FILE_GW)
56 mode |= S_IWGRP;
57 if (permissions & FILE_GX)
58 mode |= S_IXGRP;
59 if (permissions & FILE_OR)
60 mode |= S_IROTH;
61 if (permissions & FILE_OW)
62 mode |= S_IWOTH;
63 if (permissions & FILE_OX)
64 mode |= S_IXOTH;
65 if (permissions & FILE_STICKY)
66 mode |= S_ISVTX;
67 F_NOTICE(" -> " << Oct << mode);
68
69 Filesystem* pFs = pFile->getFilesystem();
70
71 st->st_dev = 0;
73 if (VFS::instance().acquireMount(pFs, mount)) {
74 if (mount.id() > PosixBlock::MaximumMinor) {
75 SYSCALL_ERROR(ValueTooLarge);
76 return false;
77 }
78 st->st_dev = PosixBlock::encode(mount.filesystem()->getDisk() ? PosixBlock::MountedMajor : 0,
79 mount.id());
80 }
81 F_NOTICE(" -> " << st->st_dev);
82 st->st_ino = attributes.inode ? attributes.inode : pFile->getInode();
83 F_NOTICE(" -> " << st->st_ino);
84 st->st_mode = mode;
85 st->st_nlink = attributes.links;
86 st->st_uid = posix_visible_id(false, attributes.uid);
87 st->st_gid = posix_visible_id(true, attributes.gid);
88 F_NOTICE(" -> uid=" << Dec << st->st_uid);
89 F_NOTICE(" -> gid=" << Dec << st->st_gid);
90 st->st_rdev = (pFile->isBlockDevice() || pFile->isCharacterDevice()) ? pFile->deviceNumber() : 0;
91 st->st_size = attributes.size;
92 F_NOTICE(" -> " << st->st_size);
93 st->st_atime = attributes.accessed;
94 st->st_mtime = attributes.modified;
95 st->st_ctime = attributes.changed;
96 st->st_blksize = pFile->getBlockSize();
97 st->st_blocks = attributes.blocks;
98
99 // Special fixups
100 if (pFs == g_pDevFs) {
101 if (pFile->getName() == nullName) {
102 F_NOTICE("/dev/null, fixing st_rdev");
103 // major/minor device numbers
104 st->st_rdev = 0x0103;
105 } else if (ConsoleManager::instance().isConsole(pFile)) {
107 ConsoleFile* pConsole = static_cast<ConsoleFile*>(pFile);
108 st->st_rdev = 0x8800 | pConsole->getConsoleNumber();
109 }
110 }
111
112 return true;
113}
114
115bool posix_chmod_file(File* pFile, mode_t mode) {
116 // Privilege-changing mode bits have no complete execution policy yet.
117 if (mode & (S_ISUID | S_ISGID)) {
118 SYSCALL_ERROR(OperationNotSupported);
119 return false;
120 }
121 FilesystemCredentials credentials;
122 if (!Process::currentFilesystemCredentials(credentials) ||
123 (credentials.uid != pFile->getUid() && !posix_global_capable(PosixCapabilities::Fowner))) {
124 SYSCALL_ERROR(NotEnoughPermissions);
125 return false;
126 }
127
129 uint32_t permissions = 0;
130 if (mode & S_IRUSR)
131 permissions |= FILE_UR;
132 if (mode & S_IWUSR)
133 permissions |= FILE_UW;
134 if (mode & S_IXUSR)
135 permissions |= FILE_UX;
136 if (mode & S_IRGRP)
137 permissions |= FILE_GR;
138 if (mode & S_IWGRP)
139 permissions |= FILE_GW;
140 if (mode & S_IXGRP)
141 permissions |= FILE_GX;
142 if (mode & S_IROTH)
143 permissions |= FILE_OR;
144 if (mode & S_IWOTH)
145 permissions |= FILE_OW;
146 if (mode & S_IXOTH)
147 permissions |= FILE_OX;
148 if (mode & S_ISVTX)
149 permissions |= FILE_STICKY;
150 pFile->setPermissions(permissions);
151
152 return true;
153}
154
155bool posix_chown_file(File* pFile, uid_t owner, gid_t group) {
156 FilesystemCredentials credentials;
157 if (!Process::currentFilesystemCredentials(credentials)) {
158 SYSCALL_ERROR(NotEnoughPermissions);
159 return false;
160 }
161 auto attributes = pFile->getAttributes();
162 uint32_t newOwner = attributes.uid, newGroup = attributes.gid;
163 if ((owner != UINT32_MAX && !posix_global_id(false, owner, newOwner)) ||
164 (group != UINT32_MAX && !posix_global_id(true, group, newGroup))) {
165 SYSCALL_ERROR(InvalidArgument);
166 return false;
167 }
168 if (!posix_global_capable(PosixCapabilities::Chown) &&
169 (credentials.uid != attributes.uid || newOwner != attributes.uid ||
170 (newGroup != attributes.gid && !credentials.inGroup(newGroup)))) {
171 SYSCALL_ERROR(NotEnoughPermissions);
172 return false;
173 }
174 if (owner == UINT32_MAX && group == UINT32_MAX) {
175 pFile->setTimes(0, 0, false, false);
176 return true;
177 }
178 return pFile->setOwnership(newOwner, newGroup, owner != UINT32_MAX, group != UINT32_MAX);
179}
Definition File.h:75
String getName() const
Definition File.cc:782
virtual bool isSocket() const
Definition File.cc:816
virtual bool isSymlink()
Definition File.cc:800
virtual bool isDirectory()
Definition File.cc:804
virtual bool isFifo() const
Definition File.cc:812
virtual bool isPipe() const
Definition File.cc:808
virtual size_t getBlockSize() const
Definition File.cc:1077
Disk * getDisk()
Definition Filesystem.h:145
static VFS & instance()
Definition VFS.cc:311
@ Oct
Definition Log.h:128
@ Dec
Definition Log.h:126