2#include "file-metadata.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/syscallError.h"
6#include "DevFs-block.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"
15bool posix_stat_file(
const char* name,
File* pFile,
struct stat* st) {
19 if (pFile->isCharacterDevice() ||
20 (pFile->getFilesystem() == g_pDevFs && pFile->
getName() == nullName)) {
21 F_NOTICE(
" -> S_IFCHR");
23 }
else if (pFile->isBlockDevice()) {
26 F_NOTICE(
" -> S_IFDIR");
29 F_NOTICE(
" -> S_IFLNK");
32 F_NOTICE(
" -> S_FIFO");
35 F_NOTICE(
" -> S_SOCK");
38 F_NOTICE(
" -> S_IFREG");
43 ByteSet(st, 0,
sizeof(*st));
46 uint32_t permissions = attributes.permissions;
47 if (permissions & FILE_UR)
49 if (permissions & FILE_UW)
51 if (permissions & FILE_UX)
53 if (permissions & FILE_GR)
55 if (permissions & FILE_GW)
57 if (permissions & FILE_GX)
59 if (permissions & FILE_OR)
61 if (permissions & FILE_OW)
63 if (permissions & FILE_OX)
65 if (permissions & FILE_STICKY)
67 F_NOTICE(
" -> " <<
Oct << mode);
74 if (mount.id() > PosixBlock::MaximumMinor) {
75 SYSCALL_ERROR(ValueTooLarge);
78 st->st_dev = PosixBlock::encode(mount.filesystem()->
getDisk() ? PosixBlock::MountedMajor : 0,
81 F_NOTICE(
" -> " << st->st_dev);
82 st->st_ino = attributes.inode ? attributes.inode : pFile->getInode();
83 F_NOTICE(
" -> " << st->st_ino);
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;
97 st->st_blocks = attributes.blocks;
100 if (pFs == g_pDevFs) {
101 if (pFile->
getName() == nullName) {
102 F_NOTICE(
"/dev/null, fixing st_rdev");
104 st->st_rdev = 0x0103;
105 }
else if (ConsoleManager::instance().isConsole(pFile)) {
108 st->st_rdev = 0x8800 | pConsole->getConsoleNumber();
115bool posix_chmod_file(
File* pFile, mode_t mode) {
117 if (mode & (S_ISUID | S_ISGID)) {
118 SYSCALL_ERROR(OperationNotSupported);
122 if (!Process::currentFilesystemCredentials(credentials) ||
123 (credentials.uid != pFile->getUid() && !posix_global_capable(PosixCapabilities::Fowner))) {
124 SYSCALL_ERROR(NotEnoughPermissions);
129 uint32_t permissions = 0;
131 permissions |= FILE_UR;
133 permissions |= FILE_UW;
135 permissions |= FILE_UX;
137 permissions |= FILE_GR;
139 permissions |= FILE_GW;
141 permissions |= FILE_GX;
143 permissions |= FILE_OR;
145 permissions |= FILE_OW;
147 permissions |= FILE_OX;
149 permissions |= FILE_STICKY;
150 pFile->setPermissions(permissions);
155bool posix_chown_file(
File* pFile, uid_t owner, gid_t group) {
157 if (!Process::currentFilesystemCredentials(credentials)) {
158 SYSCALL_ERROR(NotEnoughPermissions);
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);
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);
174 if (owner == UINT32_MAX && group == UINT32_MAX) {
175 pFile->setTimes(0, 0,
false,
false);
178 return pFile->setOwnership(newOwner, newGroup, owner != UINT32_MAX, group != UINT32_MAX);
virtual bool isSocket() const
virtual bool isDirectory()
virtual bool isFifo() const
virtual bool isPipe() const
virtual size_t getBlockSize() const