20 #include "modules/system/console/Console.h" 22 #include "modules/system/users/Group.h" 23 #include "modules/system/users/User.h" 24 #include "modules/system/users/UserManager.h" 25 #include "modules/system/vfs/Directory.h" 26 #include "modules/system/vfs/File.h" 27 #include "modules/system/vfs/LockedFile.h" 29 #include "modules/system/vfs/Pipe.h" 30 #include "modules/system/vfs/Symlink.h" 31 #include "modules/system/vfs/VFS.h" 32 #include "pedigree/kernel/compiler.h" 33 #include "pedigree/kernel/machine/Disk.h" 34 #include "pedigree/kernel/machine/Keyboard.h" 35 #include "pedigree/kernel/machine/KeymapManager.h" 36 #include "pedigree/kernel/machine/Machine.h" 37 #include "pedigree/kernel/process/Process.h" 38 #include "pedigree/kernel/processor/MemoryRegion.h" 39 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 40 #include "pedigree/kernel/processor/Processor.h" 41 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 42 #include "pedigree/kernel/processor/types.h" 43 #include "pedigree/kernel/syscallError.h" 44 #include "pedigree/kernel/utilities/PointerGuard.h" 45 #include "pedigree/kernel/utilities/Tree.h" 46 #include "pedigree/kernel/utilities/utility.h" 48 #include "modules/subsys/posix/IoEvent.h" 49 #include "pedigree/kernel/Subsystem.h" 50 #include <FileDescriptor.h> 51 #include <PosixProcess.h> 52 #include <PosixSubsystem.h> 54 #include "console-syscalls.h" 55 #include "file-syscalls.h" 56 #include "net-syscalls.h" 57 #include "pipe-syscalls.h" 63 #include <sys/ioctl.h> 66 #include <sys/statfs.h> 67 #include <sys/statvfs.h> 72 #define ENABLE_VERBOSE_NORMALISATION 0 74 extern int posix_getpid();
81 unsigned short d_reclen;
85 extern DevFs *g_pDevFs;
91 #define CHECK_FLAG(a, b) (((a) & (b)) == (b)) 94 (Processor::information().getCurrentThread()->getParent()->getCwd()) 100 if (pStockProcess->
getType() != Process::Posix)
115 return pSubsystem->
findFile(name, cwd);
118 static File *traverseSymlink(
File *file)
123 SYSCALL_ERROR(DoesNotExist);
133 SYSCALL_ERROR(DoesNotExist);
137 if (loopDetect.
lookup(file))
139 SYSCALL_ERROR(LoopExists);
143 loopDetect.
insert(file, file);
149 static bool doChdir(
File *dir)
154 target = traverseSymlink(dir);
157 F_NOTICE(
"Symlink traversal failed.");
158 SYSCALL_ERROR(DoesNotExist);
166 File *pRealFile = dir;
182 SYSCALL_ERROR(NotADirectory);
187 SYSCALL_ERROR(DoesNotExist);
195 doStat(
const char *name,
File *pFile,
struct stat *st,
bool traverse =
true)
199 pFile = traverseSymlink(pFile);
202 F_NOTICE(
" -> Symlink traversal failed");
209 if (ConsoleManager::instance().isConsole(pFile) ||
210 (name && !StringCompare(name,
"/dev/null")) ||
211 (pFile && pFile->
getName() ==
"null"))
213 F_NOTICE(
" -> S_IFCHR");
218 F_NOTICE(
" -> S_IFDIR");
223 F_NOTICE(
" -> S_IFLNK");
228 F_NOTICE(
" -> S_FIFO");
233 F_NOTICE(
" -> S_SOCK");
238 F_NOTICE(
" -> S_IFREG");
243 ByteSet(st, 0,
sizeof(*st));
245 uint32_t permissions = pFile->getPermissions();
246 if (permissions & FILE_UR)
248 if (permissions & FILE_UW)
250 if (permissions & FILE_UX)
252 if (permissions & FILE_GR)
254 if (permissions & FILE_GW)
256 if (permissions & FILE_GX)
258 if (permissions & FILE_OR)
260 if (permissions & FILE_OW)
262 if (permissions & FILE_OX)
264 if (permissions & FILE_STICKY)
266 F_NOTICE(
" -> " <<
Oct << mode);
272 static_cast<short>(
reinterpret_cast<uintptr_t
>(pFile->getFilesystem()));
273 F_NOTICE(
" -> " << st->st_dev);
274 st->st_ino =
static_cast<short>(pFile->getInode());
275 F_NOTICE(
" -> " << st->st_ino);
278 st->st_uid = pFile->getUid();
279 st->st_gid = pFile->getGid();
280 F_NOTICE(
" -> uid=" <<
Dec << st->st_uid);
281 F_NOTICE(
" -> gid=" <<
Dec << st->st_gid);
283 st->st_size =
static_cast<int>(pFile->getSize());
284 F_NOTICE(
" -> " << st->st_size);
288 st->st_blksize =
static_cast<int>(pFile->
getBlockSize());
289 st->st_blocks = (st->st_size / st->st_blksize) +
290 ((st->st_size % st->st_blksize) ? 1 : 0);
295 if ((name && !StringCompare(name,
"/dev/null")) ||
298 F_NOTICE(
"/dev/null, fixing st_rdev");
300 st->st_rdev = 0x0103;
302 else if (ConsoleManager::instance().isConsole(pFile))
306 st->st_rdev = 0x8800 | pConsole->getConsoleNumber();
313 static bool doChmod(
File *pFile, mode_t mode)
319 size_t uid = pCurrentUser->
getId();
320 if (!(uid == pFile->getUid() || uid == 0))
322 F_NOTICE(
" -> EPERM");
325 SYSCALL_ERROR(NotEnoughPermissions);
330 uint32_t permissions = 0;
332 permissions |= FILE_UR;
334 permissions |= FILE_UW;
336 permissions |= FILE_UX;
338 permissions |= FILE_GR;
340 permissions |= FILE_GW;
342 permissions |= FILE_GX;
344 permissions |= FILE_OR;
346 permissions |= FILE_OW;
348 permissions |= FILE_OX;
350 permissions |= FILE_STICKY;
351 pFile->setPermissions(permissions);
356 static bool doChown(
File *pFile, uid_t owner, gid_t group)
359 size_t newOwner = pFile->getUid();
360 size_t newGroup = pFile->getGid();
361 if (owner != static_cast<uid_t>(-1))
365 if (group != static_cast<gid_t>(-1))
371 if (pFile->getUid() != newOwner)
375 if (pCurrentUser->
getId())
377 SYSCALL_ERROR(NotEnoughPermissions);
384 if (pFile->getGid() != newGroup)
388 if (pCurrentUser->
getId())
391 if (!pTargetGroup->
isMember(pCurrentUser))
393 SYSCALL_ERROR(NotEnoughPermissions);
400 if (pFile->getUid() != newOwner)
402 pFile->setUid(newOwner);
405 if (pFile->getGid() != newGroup)
407 pFile->setGid(newGroup);
414 static struct Remapping
424 {
"/dev",
"dev»",
nullptr,
true,
true},
425 {
"/proc",
"proc»",
"proc",
true,
false},
426 {
"/bin",
"/applications",
nullptr,
false,
false},
427 {
"/usr/bin",
"/applications",
nullptr,
false,
false},
428 {
"/lib",
"/libraries",
nullptr,
false,
false},
429 {
"/etc",
"/config",
nullptr,
false,
false},
430 {
"/tmp",
"scratch»",
"tmpfs",
true,
false},
431 {
"/var/run",
"posix-runtime»",
"tmpfs",
true,
false},
432 {
nullptr,
nullptr,
nullptr,
false,
false},
435 bool normalisePath(
String &nameToOpen,
const char *name,
bool *onDevFs)
441 bool fixFilesystemPaths = pSubsystem->
getAbi() != PosixSubsystem::LinuxAbi;
447 if (!StringCompare(name,
"/dev/tty"))
459 else if (!StringCompareN(name,
"/@/", StringLength(
"/@/")))
464 const char *newName = name + StringLength(
"/@/");
467 nameToOpen = newName;
473 struct Remapping *remap = g_Remappings;
474 #if ENABLE_VERBOSE_NORMALISATION 475 F_NOTICE(
"performing remap for '" << name <<
"'...");
478 while (remap->from !=
nullptr)
480 if (!(fixFilesystemPaths || remap->all_abis))
482 #if ENABLE_VERBOSE_NORMALISATION 484 " -> ignoring " << remap->from
485 <<
" as it is not for the current ABI");
491 #if ENABLE_VERBOSE_NORMALISATION 492 F_NOTICE(
" -> check against " << remap->from);
494 if (!StringCompare(name, remap->from))
496 #if ENABLE_VERBOSE_NORMALISATION 497 F_NOTICE(
" -> direct remap to " << remap->to);
499 nameToOpen = remap->to;
505 if (!StringCompareN(name, remap->from, StringLength(remap->from)))
507 #if ENABLE_VERBOSE_NORMALISATION 508 F_NOTICE(
" -> possibly partial remap");
513 if (*(name + StringLength(remap->from)) ==
'/')
516 nameToOpen = remap->to;
517 nameToOpen += (name + StringLength(remap->from));
518 #if ENABLE_VERBOSE_NORMALISATION 520 " -> indirect remap to create path '" << nameToOpen
528 #if ENABLE_VERBOSE_NORMALISATION 529 NOTICE(
" -> cannot use this remap as it is not actually " 530 "matching a path segment");
537 if (onDevFs && remap)
539 *onDevFs = remap->on_devfs;
552 int posix_close(
int fd)
554 #ifdef VERBOSE_KERNEL 555 F_NOTICE(
"close(" << fd <<
")");
563 ERROR(
"No subsystem for this process!");
571 SYSCALL_ERROR(BadFileDescriptor);
575 #ifndef VERBOSE_KERNEL 576 F_NOTICE(
"close(" << fd <<
")");
580 if (ConsoleManager::instance().isConsole(pFd->
file))
582 if (ConsoleManager::instance().isMasterConsole(pFd->
file))
592 int posix_open(
const char *name,
int flags,
int mode)
594 return posix_openat(AT_FDCWD, name, flags, mode);
597 int posix_read(
int fd,
char *ptr,
int len)
600 "read(" <<
Dec << fd <<
Hex <<
", " << reinterpret_cast<uintptr_t>(ptr)
601 <<
", " << len <<
")");
603 reinterpret_cast<uintptr_t>(ptr), len, PosixSubsystem::SafeWrite))
605 F_NOTICE(
" -> invalid address");
606 SYSCALL_ERROR(InvalidArgument);
617 ERROR(
"No subsystem for this process!");
625 SYSCALL_ERROR(BadFileDescriptor);
632 return posix_recv(fd, ptr, len, 0);
637 SYSCALL_ERROR(IsADirectory);
642 bool canBlock = !((pFd->
flflags & O_NONBLOCK) == O_NONBLOCK);
651 SYSCALL_ERROR(NoMoreProcesses);
652 F_NOTICE(
" -> async and nothing available to read");
665 pFd->
offset, len, reinterpret_cast<uintptr_t>(ptr), canBlock);
672 SYSCALL_ERROR(Interrupted);
673 F_NOTICE(
" -> interrupted");
684 debug.assign(ptr, nRead,
true);
685 F_NOTICE(
" -> read: '" << debug <<
"'");
688 F_NOTICE(
" -> " <<
Dec << nRead <<
Hex);
690 return static_cast<int>(nRead);
693 int posix_write(
int fd,
char *ptr,
int len,
bool nocheck)
696 "write(" << fd <<
", " << reinterpret_cast<uintptr_t>(ptr) <<
", " 700 reinterpret_cast<uintptr_t>(ptr), len, PosixSubsystem::SafeRead))
702 F_NOTICE(
" -> invalid address");
703 SYSCALL_ERROR(InvalidArgument);
712 debug.assign(ptr, len - 1,
true);
713 F_NOTICE(
"write(" << fd <<
", " << debug <<
", " << len <<
")");
723 ERROR(
"No subsystem for this process!");
731 SYSCALL_ERROR(BadFileDescriptor);
738 return posix_send(fd, ptr, len, 0);
742 uint64_t nWritten = 0;
746 pFd->
offset, len, reinterpret_cast<uintptr_t>(ptr));
750 F_NOTICE(
" -> write returns " << nWritten);
754 if (pFd->
file->
isPipe() && (nWritten == 0 && len > 0))
756 F_NOTICE(
" -> write to a broken pipe");
757 SYSCALL_ERROR(BrokenPipe);
762 return static_cast<int>(nWritten);
765 int posix_writev(
int fd,
const struct iovec *iov,
int iovcnt)
767 F_NOTICE(
"writev(" << fd <<
", <iov>, " << iovcnt <<
")");
773 SYSCALL_ERROR(InvalidArgument);
777 int totalWritten = 0;
778 for (
int i = 0; i < iovcnt; ++i)
781 "writev: iov[" << i <<
"] is @ " << iov[i].iov_base <<
", " 782 << iov[i].iov_len <<
" bytes.");
788 fd, reinterpret_cast<char *>(iov[i].iov_base), iov[i].iov_len,
803 int posix_readv(
int fd,
const struct iovec *iov,
int iovcnt)
805 F_NOTICE(
"readv(" << fd <<
", <iov>, " << iovcnt <<
")");
811 SYSCALL_ERROR(InvalidArgument);
816 for (
int i = 0; i < iovcnt; ++i)
819 "readv: iov[" << i <<
"] is @ " << iov[i].iov_base <<
", " 820 << iov[i].iov_len <<
" bytes.");
826 fd, reinterpret_cast<char *>(iov[i].iov_base), iov[i].iov_len);
840 off_t posix_lseek(
int file, off_t ptr,
int dir)
842 F_NOTICE(
"lseek(" << file <<
", " << ptr <<
", " << dir <<
")");
851 ERROR(
"No subsystem for this process!");
859 SYSCALL_ERROR(BadFileDescriptor);
863 size_t fileSize = pFd->
file->getSize();
873 pFd->
offset = fileSize + ptr;
877 return static_cast<int>(pFd->
offset);
880 int posix_link(
char *target,
char *link)
882 return posix_linkat(AT_FDCWD, target, AT_FDCWD, link, AT_SYMLINK_FOLLOW);
885 int posix_readlink(
const char *path,
char *buf,
unsigned int bufsize)
887 return posix_readlinkat(AT_FDCWD, path, buf, bufsize);
890 int posix_realpath(
const char *path,
char *buf,
size_t bufsize)
892 F_NOTICE(
"realpath");
895 reinterpret_cast<uintptr_t>(path), PATH_MAX,
896 PosixSubsystem::SafeRead) &&
898 reinterpret_cast<uintptr_t>(buf), bufsize,
899 PosixSubsystem::SafeWrite)))
901 F_NOTICE(
"realpath -> invalid address");
902 SYSCALL_ERROR(InvalidArgument);
907 normalisePath(realPath, path);
908 F_NOTICE(
" -> traversing " << realPath);
909 File *f = findFileWithAbiFallbacks(realPath, GET_CWD());
912 SYSCALL_ERROR(DoesNotExist);
916 f = traverseSymlink(f);
919 SYSCALL_ERROR(DoesNotExist);
925 SYSCALL_ERROR(NotADirectory);
931 if (actualPath.length() > (bufsize - 1))
933 SYSCALL_ERROR(NameTooLong);
938 F_NOTICE(
" -> returning " << actualPath);
939 StringCopyN(buf, static_cast<const char *>(actualPath), bufsize);
944 int posix_unlink(
char *name)
946 return posix_unlinkat(AT_FDCWD, name, 0);
949 int posix_symlink(
char *target,
char *link)
951 return posix_symlinkat(target, AT_FDCWD, link);
954 int posix_rename(
const char *source,
const char *dst)
956 return posix_renameat(AT_FDCWD, source, AT_FDCWD, dst);
959 int posix_getcwd(
char *buf,
size_t maxlen)
962 reinterpret_cast<uintptr_t>(buf), maxlen,
963 PosixSubsystem::SafeWrite))
965 F_NOTICE(
"getcwd -> invalid address");
966 SYSCALL_ERROR(InvalidArgument);
970 F_NOTICE(
"getcwd(" << maxlen <<
")");
972 File *curr = GET_CWD();
978 size_t maxLength = str.length();
979 if (maxLength > maxlen)
982 SYSCALL_ERROR(BadRange);
985 StringCopyN(buf, static_cast<const char *>(str), maxLength);
987 F_NOTICE(
" -> " << str);
989 return maxLength + 1;
992 int posix_stat(
const char *name,
struct stat *st)
994 F_NOTICE(
"stat(" << name <<
") => fstatat");
995 return posix_fstatat(AT_FDCWD, name, st, 0);
998 int posix_fstat(
int fd,
struct stat *st)
1000 F_NOTICE(
"fstat(" << fd <<
") => fstatat");
1001 return posix_fstatat(fd, 0, st, AT_EMPTY_PATH);
1004 int posix_lstat(
char *name,
struct stat *st)
1006 F_NOTICE(
"lstat(" << name <<
") => fstatat");
1007 return posix_fstatat(AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW);
1010 static int getdents_common(
1011 int fd,
size_t (*set_dent)(
File *,
void *,
size_t,
size_t),
void *buffer,
1021 ERROR(
"No subsystem for this process!");
1026 if (!pFd || !pFd->
file)
1029 F_NOTICE(
" -> bad file");
1030 SYSCALL_ERROR(BadFileDescriptor);
1036 F_NOTICE(
" -> not a directory");
1037 SYSCALL_ERROR(NotADirectory);
1043 F_NOTICE(
" -> count is zero");
1049 size_t truePosition = pFd->
offset;
1051 for (; truePosition < pDirectory->
getNumChildren() && offset < count;
1058 F_NOTICE(
" -> " << pFile->
getName());
1060 set_dent(pFile, buffer, count - offset, truePosition + 1);
1067 buffer = adjust_pointer(buffer, reclen);
1071 size_t totalCount = truePosition - pFd->
offset;
1072 pFd->
offset = truePosition;
1074 F_NOTICE(
" -> " << offset);
1079 getdents_helper(
File *file,
void *buffer,
size_t avail,
size_t next_pos)
1083 char *char_buffer =
reinterpret_cast<char *
>(buffer);
1085 size_t filenameLength = file->
getName().length();
1087 size_t reclen =
sizeof(
struct linux_dirent) + filenameLength + 2;
1095 entry->d_reclen = reclen;
1096 entry->d_off = next_pos;
1098 entry->d_ino = file->getInode();
1104 StringCopy(entry->d_name, static_cast<const char *>(file->
getName()));
1105 char_buffer[reclen - 2] = 0;
1107 char d_type = DT_UNKNOWN;
1121 char_buffer[reclen - 1] = d_type;
1127 getdents64_helper(
File *file,
void *buffer,
size_t avail,
size_t next_pos)
1129 struct dirent *entry =
reinterpret_cast<struct dirent *
>(buffer);
1131 size_t filenameLength = file->
getName().length();
1132 size_t reclen = offsetof(
struct dirent, d_name) + filenameLength +
1141 entry->d_reclen = reclen;
1142 entry->d_off = next_pos;
1144 entry->d_ino = file->getInode();
1150 StringCopy(entry->d_name, static_cast<const char *>(file->
getName()));
1151 entry->d_name[filenameLength] = 0;
1155 entry->d_type = DT_LNK;
1159 entry->d_type = DT_DIR;
1164 entry->d_type = DT_REG;
1170 int posix_getdents(
int fd,
struct linux_dirent *ents,
int count)
1172 F_NOTICE(
"getdents(" << fd <<
")");
1174 reinterpret_cast<uintptr_t>(ents), count,
1175 PosixSubsystem::SafeWrite))
1177 F_NOTICE(
"getdents -> invalid address");
1178 SYSCALL_ERROR(InvalidArgument);
1182 return getdents_common(fd, getdents_helper, ents, count);
1185 int posix_getdents64(
int fd,
struct dirent *ents,
int count)
1187 F_NOTICE(
"getdents64(" << fd <<
")");
1189 reinterpret_cast<uintptr_t>(ents), count,
1190 PosixSubsystem::SafeWrite))
1192 F_NOTICE(
"getdents64 -> invalid address");
1193 SYSCALL_ERROR(InvalidArgument);
1197 return getdents_common(fd, getdents64_helper, ents, count);
1200 int posix_ioctl(
int fd,
size_t command,
void *buf)
1203 "ioctl(" <<
Dec << fd <<
", " <<
Hex << command <<
", " 1204 << reinterpret_cast<uintptr_t>(buf) <<
")");
1212 ERROR(
"No subsystem for this process!");
1220 F_NOTICE(
" -> ioctl for a file that doesn't exist");
1221 SYSCALL_ERROR(BadFileDescriptor);
1227 F_NOTICE(
" -> fd " << fd <<
" is not supposed to be ioctl'd");
1228 SYSCALL_ERROR(InvalidArgument);
1244 F_NOTICE(
" -> KDGETLED, arg=" << buf);
1245 char *cbuf =
reinterpret_cast<char *
>(buf);
1253 F_NOTICE(
" -> KDSETLED, arg=" << buf);
1254 uintptr_t leds =
reinterpret_cast<uintptr_t
>(buf);
1261 F_NOTICE(
" -> KDGKBTYPE");
1262 if (ConsoleManager::instance().isConsole(f->
file))
1265 *
reinterpret_cast<int *
>(buf) = 0x02;
1270 SYSCALL_ERROR(NotAConsole);
1278 F_NOTICE(
" -> KDSETMODE (stubbed), arg=" << buf);
1279 if (buf == reinterpret_cast<void *>(1))
1281 g_pDevFs->getTerminalManager().setSystemMode(
1282 VirtualTerminalManager::Graphics);
1286 g_pDevFs->getTerminalManager().setSystemMode(
1287 VirtualTerminalManager::Text);
1294 F_NOTICE(
" -> KDGETMODE");
1295 switch (g_pDevFs->getTerminalManager().getSystemMode())
1297 case VirtualTerminalManager::Graphics:
1298 *
reinterpret_cast<int *
>(buf) = 1;
1300 case VirtualTerminalManager::Text:
1301 *
reinterpret_cast<int *
>(buf) = 0;
1309 F_NOTICE(
" -> KDGKBMODE (stubbed), arg=" << buf);
1315 F_NOTICE(
" -> KDSKBMODE, arg=" << buf);
1317 size_t consoleNumber = 0;
1318 if (ConsoleManager::instance().isConsole(f->
file))
1321 consoleNumber = pConsole->getPhysicalConsoleNumber();
1322 if (consoleNumber == ~0U)
1324 ERROR(
"KDSKBMODE used on something that is not a VT");
1330 SYSCALL_ERROR(NotAConsole);
1334 long mode =
reinterpret_cast<long>(buf);
1337 g_pDevFs->getTerminalManager().setInputMode(
1338 consoleNumber, TextIO::Raw);
1342 g_pDevFs->getTerminalManager().setInputMode(
1343 consoleNumber, TextIO::Standard);
1351 F_NOTICE(
" -> KDGKBENT, arg=" << buf);
1352 POSIX_VERBOSE_LOG(
"io",
" -> KDGKBENT, arg=" << buf);
1355 bool shift = kbent->kb_table & 0x1;
1356 bool altgr = kbent->kb_table & 0x2;
1357 bool ctrl = kbent->kb_table & 0x4;
1358 bool alt = kbent->kb_table & 0x8;
1361 KeymapManager::EscapeState escape = KeymapManager::EscapeNone;
1364 kbent->kb_index, escape);
1367 ctrl, shift, alt, altgr, 0, keyCode);
1371 " -> no keymap entry for table #" <<
Dec << kbent->kb_table
1372 <<
" index #" <<
Hex 1373 << kbent->kb_index);
1375 0xF000 |
static_cast<uint16_t
>(entry->value & 0xFFFF);
1379 kbent->kb_value = 0;
1383 "io",
" -> val for table #" <<
Dec << kbent->kb_table <<
" #" 1384 <<
Hex << kbent->kb_index
1385 <<
" is now " << kbent->kb_value
1392 F_NOTICE(
" -> KDSKBENT (stubbed), arg=" << buf);
1393 POSIX_VERBOSE_LOG(
"io",
" -> KDSKBENT (stubbed), arg=" << buf);
1398 F_NOTICE(
" -> KDKBDREP (stubbed), arg=" << buf);
1403 if (ConsoleManager::instance().isConsole(f->
file))
1405 return posix_tcgetattr(
1406 fd, reinterpret_cast<struct termios *>(buf));
1410 SYSCALL_ERROR(NotAConsole);
1417 if (ConsoleManager::instance().isConsole(f->
file))
1419 return posix_tcsetattr(
1420 fd, TCSANOW, reinterpret_cast<struct termios *>(buf));
1424 SYSCALL_ERROR(NotAConsole);
1431 if (ConsoleManager::instance().isConsole(f->
file))
1433 return posix_tcsetattr(
1434 fd, TCSADRAIN, reinterpret_cast<struct termios *>(buf));
1438 SYSCALL_ERROR(NotAConsole);
1445 if (ConsoleManager::instance().isConsole(f->
file))
1447 return posix_tcsetattr(
1448 fd, TCSAFLUSH, reinterpret_cast<struct termios *>(buf));
1452 SYSCALL_ERROR(NotAConsole);
1459 if (ConsoleManager::instance().isConsole(f->
file))
1461 pid_t pgrp = posix_tcgetpgrp(fd);
1462 *
reinterpret_cast<pid_t *
>(buf) = pgrp;
1467 SYSCALL_ERROR(NotAConsole);
1474 if (ConsoleManager::instance().isConsole(f->
file))
1476 return posix_tcsetpgrp(fd, *reinterpret_cast<pid_t *>(buf));
1480 SYSCALL_ERROR(NotAConsole);
1487 if (ConsoleManager::instance().isConsole(f->
file))
1489 return console_flush(f->
file, 0);
1493 SYSCALL_ERROR(NotAConsole);
1500 if (ConsoleManager::instance().isConsole(f->
file))
1502 F_NOTICE(
" -> TIOCGWINSZ");
1503 return console_getwinsize(
1504 f->
file, reinterpret_cast<struct winsize *>(buf));
1508 SYSCALL_ERROR(NotAConsole);
1515 if (ConsoleManager::instance().isConsole(f->
file))
1517 const struct winsize *ws =
1518 reinterpret_cast<const struct winsize *
>(buf);
1520 " -> TIOCSWINSZ " <<
Dec << ws->ws_col <<
"x" << ws->ws_row
1522 return console_setwinsize(f->
file, ws);
1526 SYSCALL_ERROR(NotAConsole);
1533 if (ConsoleManager::instance().isConsole(f->
file))
1535 F_NOTICE(
" -> TIOCSCTTY");
1536 return console_setctty(
1537 fd, reinterpret_cast<uintptr_t>(buf) == 1);
1541 SYSCALL_ERROR(NotAConsole);
1548 F_NOTICE(
" -> TIOCGPTN");
1549 unsigned int *out =
reinterpret_cast<unsigned int *
>(buf);
1550 unsigned int result = console_getptn(fd);
1553 F_NOTICE(
" -> ok, returning " << result);
1560 F_NOTICE(
" -> failed!");
1567 F_NOTICE(
" -> FIONBIO");
1571 int a = *
reinterpret_cast<int *
>(buf);
1574 F_NOTICE(
" -> set non-blocking");
1579 F_NOTICE(
" -> set blocking");
1592 F_NOTICE(
" -> VT_OPENQRY (stubbed)");
1594 int *ibuf =
reinterpret_cast<int *
>(buf);
1596 size_t newTty = g_pDevFs->getTerminalManager().
openInactive();
1599 NOTICE(
"VT_OPENQRY => " << newTty);
1613 F_NOTICE(
" -> VT_GETMODE (stubbed)");
1618 g_pDevFs->getTerminalManager().getCurrentTerminalNumber();
1628 F_NOTICE(
" -> VT_SETMODE (stubbed)");
1631 reinterpret_cast<const struct
vt_mode *
>(buf);
1636 g_pDevFs->getTerminalManager().getCurrentTerminalNumber();
1644 F_NOTICE(
" -> VT_GETSTATE (stubbed)");
1647 *stat = g_pDevFs->getTerminalManager().getState();
1654 F_NOTICE(
" -> VT_RELDISP (stubbed)");
1657 uintptr_t ibuf =
reinterpret_cast<uintptr_t
>(buf);
1660 NOTICE(
" -> switch disallowed");
1662 VirtualTerminalManager::Disallowed);
1666 NOTICE(
" -> switch allowed");
1668 VirtualTerminalManager::Allowed);
1672 NOTICE(
" -> switch acknowledged");
1680 uintptr_t ttyNum =
reinterpret_cast<uintptr_t
>(buf);
1681 F_NOTICE(
" -> VT_ACTIVATE -> " << ttyNum);
1682 g_pDevFs->getTerminalManager().
activate(ttyNum - 1);
1693 " -> invalid combination of fd " << fd <<
" and ioctl " <<
Hex 1695 SYSCALL_ERROR(InvalidArgument);
1699 int posix_chdir(
const char *path)
1704 reinterpret_cast<uintptr_t>(path), PATH_MAX,
1705 PosixSubsystem::SafeRead))
1707 F_NOTICE(
"chdir -> invalid address");
1708 SYSCALL_ERROR(InvalidArgument);
1712 F_NOTICE(
"chdir(" << path <<
")");
1715 normalisePath(realPath, path);
1717 File *dir = findFileWithAbiFallbacks(realPath, GET_CWD());
1720 F_NOTICE(
"Does not exist.");
1721 SYSCALL_ERROR(DoesNotExist);
1725 return doChdir(dir) ? 0 : -1;
1728 int posix_dup(
int fd)
1730 F_NOTICE(
"dup(" << fd <<
")");
1739 ERROR(
"No subsystem for this process!");
1746 SYSCALL_ERROR(BadFileDescriptor);
1750 size_t newFd = pSubsystem->
getFd();
1756 return static_cast<int>(newFd);
1759 int posix_dup2(
int fd1,
int fd2)
1761 F_NOTICE(
"dup2(" << fd1 <<
", " << fd2 <<
")");
1765 SYSCALL_ERROR(BadFileDescriptor);
1779 ERROR(
"No subsystem for this process!");
1786 SYSCALL_ERROR(BadFileDescriptor);
1804 int posix_mkdir(
const char *name,
int mode)
1806 return posix_mkdirat(AT_FDCWD, name, mode);
1809 int posix_rmdir(
const char *path)
1811 return posix_unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
1814 int posix_isatty(
int fd)
1823 ERROR(
"No subsystem for this process!");
1831 ERROR(
"isatty: no such file descriptor (" <<
Dec << fd <<
Hex <<
")");
1835 int result = ConsoleManager::instance().isConsole(pFd->
file) ? 1 : 0;
1836 NOTICE(
"isatty(" << fd <<
") -> " << result);
1840 int posix_fcntl(
int fd,
int cmd,
void *arg)
1843 F_NOTICE(
"fcntl(" << fd <<
", " <<
cmd <<
", " << arg <<
")");
1852 ERROR(
"No subsystem for this process!");
1859 SYSCALL_ERROR(BadFileDescriptor);
1869 size_t fd2 =
reinterpret_cast<size_t>(arg);
1879 return static_cast<int>(fd2);
1883 size_t fd2 = pSubsystem->
getFd();
1892 return static_cast<int>(fd2);
1896 F_NOTICE(
" -> get fd flags");
1899 F_NOTICE(
" -> set fd flags: " << arg);
1900 f->
fdflags =
reinterpret_cast<size_t>(arg);
1903 F_NOTICE(
" -> get flags " << f->
flflags);
1906 F_NOTICE(
" -> set flags " << arg);
1907 f->
flflags =
reinterpret_cast<size_t>(arg) &
1908 (O_APPEND | O_NONBLOCK | O_CLOEXEC);
1909 F_NOTICE(
" -> new flags " << f->
flflags);
1914 F_NOTICE(
" -> fcntl locks (stubbed)");
1918 F_NOTICE(
" -> F_GETOWN (stubbed)");
1922 F_NOTICE(
" -> F_SETOWN");
1928 NOTICE(
"Adding ioevent to thread");
1936 "F_SETOWN on something that can't raise events [fd=" 1937 << fd <<
" file=" << f->
file 1945 WARNING(
"fcntl: unknown control " <<
cmd <<
" on fd " << fd);
1948 SYSCALL_ERROR(Unimplemented);
1952 void *posix_mmap(
void *addr,
size_t len,
int prot,
int flags,
int fd, off_t off)
1956 " -> addr=" << addr <<
", len=" << len <<
", prot=" << prot
1957 <<
", flags=" << flags <<
", fildes=" << fd
1958 <<
", off=" << off <<
".");
1967 ERROR(
"No subsystem for this process!");
1972 void *finalAddress = 0;
1978 uintptr_t sanityAddress =
reinterpret_cast<uintptr_t
>(addr);
1984 if (flags & MAP_FIXED)
1987 SYSCALL_ERROR(InvalidArgument);
1988 F_NOTICE(
" -> mmap given invalid fixed address");
2000 if (!len || (sanityAddress & (pageSz - 1)))
2002 SYSCALL_ERROR(InvalidArgument);
2008 if (prot & PROT_NONE)
2010 perms = MemoryMappedObject::None;
2015 perms = MemoryMappedObject::Read;
2016 if (prot & PROT_WRITE)
2017 perms |= MemoryMappedObject::Write;
2018 if (prot & PROT_EXEC)
2019 perms |= MemoryMappedObject::Exec;
2022 if (flags & MAP_ANON)
2024 if (flags & MAP_SHARED)
2027 " -> failed (MAP_SHARED cannot be used with MAP_ANONYMOUS)");
2028 SYSCALL_ERROR(InvalidArgument);
2037 SYSCALL_ERROR(OutOfMemory);
2038 F_NOTICE(
" -> failed (mapAnon)!");
2042 F_NOTICE(
" -> " << sanityAddress);
2044 finalAddress =
reinterpret_cast<void *
>(sanityAddress);
2052 SYSCALL_ERROR(BadFileDescriptor);
2066 fileToMap, prot & PROT_READ,
2067 (prot & PROT_WRITE) && (flags & MAP_SHARED), prot & PROT_EXEC))
2071 <<
" failed due to permissions.");
2075 F_NOTICE(
"mmap: file name is " << fileToMap->
getFullPath());
2079 bool bCopyOnWrite = (flags & MAP_SHARED) == 0;
2081 fileToMap, sanityAddress, len, perms, off, bCopyOnWrite);
2085 SYSCALL_ERROR(OutOfMemory);
2086 F_NOTICE(
" -> failed (mapFile)!");
2090 F_NOTICE(
" -> " << sanityAddress);
2092 finalAddress =
reinterpret_cast<void *
>(sanityAddress);
2096 return finalAddress;
2099 int posix_msync(
void *p,
size_t len,
int flags)
2103 " -> addr=" << p <<
", len=" << len <<
", flags=" <<
Hex << flags);
2105 uintptr_t addr =
reinterpret_cast<uintptr_t
>(p);
2109 if (!len || (addr & (pageSz - 1)))
2111 SYSCALL_ERROR(InvalidArgument);
2115 if ((flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC)) != 0)
2117 SYSCALL_ERROR(InvalidArgument);
2124 SYSCALL_ERROR(OutOfMemory);
2128 if (flags & MS_INVALIDATE)
2140 int posix_mprotect(
void *p,
size_t len,
int prot)
2142 F_NOTICE(
"mprotect");
2143 F_NOTICE(
" -> addr=" << p <<
", len=" << len <<
", prot=" <<
Hex << prot);
2145 uintptr_t addr =
reinterpret_cast<uintptr_t
>(p);
2149 if (!len || (addr & (pageSz - 1)))
2151 SYSCALL_ERROR(InvalidArgument);
2158 SYSCALL_ERROR(OutOfMemory);
2164 if (prot & PROT_NONE)
2166 perms = MemoryMappedObject::None;
2171 perms = MemoryMappedObject::Read;
2172 if (prot & PROT_WRITE)
2173 perms |= MemoryMappedObject::Write;
2174 if (prot & PROT_EXEC)
2175 perms |= MemoryMappedObject::Exec;
2186 int posix_munmap(
void *addr,
size_t len)
2189 "munmap(" << reinterpret_cast<uintptr_t>(addr) <<
", " << len <<
")");
2193 SYSCALL_ERROR(InvalidArgument);
2202 int posix_access(
const char *name,
int amode)
2204 return posix_faccessat(AT_FDCWD, name, amode, 0);
2207 int posix_ftruncate(
int a, off_t b)
2209 F_NOTICE(
"ftruncate(" << a <<
", " << b <<
")");
2218 ERROR(
"No subsystem for this process!");
2226 SYSCALL_ERROR(BadFileDescriptor);
2237 else if (static_cast<size_t>(b) == pFile->getSize())
2240 else if (static_cast<size_t>(b) < pFile->getSize())
2248 size_t currSize = pFile->getSize();
2249 size_t numExtraBytes = b - currSize;
2250 NOTICE(
"Extending by " << numExtraBytes <<
" bytes");
2251 uint8_t *nullBuffer =
new uint8_t[numExtraBytes];
2252 NOTICE(
"Got the buffer");
2253 ByteSet(nullBuffer, 0, numExtraBytes);
2254 NOTICE(
"Zeroed the buffer");
2256 currSize, numExtraBytes, reinterpret_cast<uintptr_t>(nullBuffer));
2257 NOTICE(
"Deleting the buffer");
2258 delete[] nullBuffer;
2264 int posix_fsync(
int fd)
2266 F_NOTICE(
"fsync(" << fd <<
")");
2275 ERROR(
"No subsystem for this process!");
2283 SYSCALL_ERROR(BadFileDescriptor);
2293 pedigree_get_mount(
char *mount_buf,
char *info_buf,
size_t n)
2296 reinterpret_cast<uintptr_t>(mount_buf), PATH_MAX,
2297 PosixSubsystem::SafeWrite) &&
2299 reinterpret_cast<uintptr_t>(info_buf), PATH_MAX,
2300 PosixSubsystem::SafeWrite)))
2302 F_NOTICE(
"pedigree_get_mount -> invalid address");
2303 SYSCALL_ERROR(InvalidArgument);
2307 NOTICE(
"pedigree_get_mount(" <<
Dec << n <<
Hex <<
")");
2314 for (VFSMountTree::Iterator it = mounts.begin(); it != mounts.end(); it++)
2317 StringList *pList = it.value();
2320 for (StringList::Iterator it2 = pList->begin(); it2 != pList->end();
2338 StringCopy(mount_buf, static_cast<const char *>(mount));
2339 StringCopy(info_buf, static_cast<const char *>(info));
2349 int posix_chmod(
const char *path, mode_t mode)
2351 return posix_fchmodat(AT_FDCWD, path, mode, 0);
2354 int posix_chown(
const char *path, uid_t owner, gid_t group)
2356 return posix_fchownat(AT_FDCWD, path, owner, group, 0);
2359 int posix_fchmod(
int fd, mode_t mode)
2361 return posix_fchmodat(fd,
nullptr, mode, AT_EMPTY_PATH);
2364 int posix_fchown(
int fd, uid_t owner, gid_t group)
2366 return posix_fchownat(fd,
nullptr, owner, group, AT_EMPTY_PATH);
2369 int posix_fchdir(
int fd)
2371 F_NOTICE(
"fchdir(" << fd <<
")");
2380 ERROR(
"No subsystem for this process!");
2388 SYSCALL_ERROR(BadFileDescriptor);
2393 return doChdir(file) ? 0 : -1;
2396 static int statvfs_doer(
Filesystem *pFs,
struct statvfs *buf)
2400 SYSCALL_ERROR(DoesNotExist);
2405 buf->f_bsize = 4096;
2406 buf->f_frsize = 512;
2407 buf->f_blocks =
static_cast<fsblkcnt_t
>(-1);
2408 buf->f_bfree =
static_cast<fsblkcnt_t
>(-1);
2409 buf->f_bavail =
static_cast<fsblkcnt_t
>(-1);
2411 buf->f_ffree =
static_cast<fsfilcnt_t
>(-1);
2412 buf->f_favail =
static_cast<fsfilcnt_t
>(-1);
2414 buf->f_flag = (pFs->
isReadOnly() ? ST_RDONLY : 0) |
2421 int posix_fstatvfs(
int fd,
struct statvfs *buf)
2424 reinterpret_cast<uintptr_t>(buf),
sizeof(
struct statvfs),
2425 PosixSubsystem::SafeWrite))
2427 F_NOTICE(
"fstatvfs -> invalid address");
2428 SYSCALL_ERROR(InvalidArgument);
2432 F_NOTICE(
"fstatvfs(" << fd <<
")");
2441 ERROR(
"No subsystem for this process!");
2449 SYSCALL_ERROR(BadFileDescriptor);
2455 return statvfs_doer(file->getFilesystem(), buf);
2458 int posix_statvfs(
const char *path,
struct statvfs *buf)
2461 reinterpret_cast<uintptr_t>(path), PATH_MAX,
2462 PosixSubsystem::SafeRead) &&
2464 reinterpret_cast<uintptr_t>(buf),
sizeof(
struct statvfs),
2465 PosixSubsystem::SafeWrite)))
2467 F_NOTICE(
"statvfs -> invalid address");
2468 SYSCALL_ERROR(InvalidArgument);
2472 F_NOTICE(
"statvfs(" << path <<
")");
2475 normalisePath(realPath, path);
2477 File *file = findFileWithAbiFallbacks(realPath, GET_CWD());
2480 SYSCALL_ERROR(DoesNotExist);
2485 file = traverseSymlink(file);
2489 return statvfs_doer(file->getFilesystem(), buf);
2492 int posix_utime(
const char *path,
const struct utimbuf *times)
2495 reinterpret_cast<uintptr_t>(path), PATH_MAX,
2496 PosixSubsystem::SafeRead) &&
2498 reinterpret_cast<uintptr_t>(times),
2499 sizeof(
struct utimbuf), PosixSubsystem::SafeRead))))
2501 F_NOTICE(
"utimes -> invalid address");
2502 SYSCALL_ERROR(InvalidArgument);
2506 F_NOTICE(
"utime(" << path <<
")");
2509 normalisePath(realPath, path);
2511 File *file = findFileWithAbiFallbacks(realPath, GET_CWD());
2514 SYSCALL_ERROR(DoesNotExist);
2519 file = traverseSymlink(file);
2529 Time::Timestamp accessTime;
2530 Time::Timestamp modifyTime;
2533 accessTime = times->actime * Time::Multiplier::Second;
2534 modifyTime = times->modtime * Time::Multiplier::Second;
2538 accessTime = modifyTime = Time::getTime();
2547 int posix_utimes(
const char *path,
const struct timeval *times)
2549 return posix_futimesat(AT_FDCWD, path, times);
2552 int posix_chroot(
const char *path)
2555 reinterpret_cast<uintptr_t>(path), PATH_MAX,
2556 PosixSubsystem::SafeRead))
2558 F_NOTICE(
"chroot -> invalid address");
2559 SYSCALL_ERROR(InvalidArgument);
2563 F_NOTICE(
"chroot(" << path <<
")");
2566 normalisePath(realPath, path);
2568 File *file = findFileWithAbiFallbacks(realPath, GET_CWD());
2571 SYSCALL_ERROR(DoesNotExist);
2576 file = traverseSymlink(file);
2583 SYSCALL_ERROR(NotADirectory);
2594 int posix_flock(
int fd,
int operation)
2596 F_NOTICE(
"flock(" << fd <<
", " << operation <<
")");
2597 F_NOTICE(
" -> flock is a no-op stub");
2601 static File *check_dirfd(
int dirfd,
int flags = 0)
2610 F_NOTICE(
" -> No subsystem for this process!");
2614 File *cwd = GET_CWD();
2615 if (dirfd != AT_FDCWD)
2620 F_NOTICE(
" -> dirfd is a bad fd");
2621 SYSCALL_ERROR(BadFileDescriptor);
2626 if ((flags & AT_EMPTY_PATH) == 0)
2630 F_NOTICE(
" -> dirfd is not a directory");
2631 SYSCALL_ERROR(NotADirectory);
2642 int posix_openat(
int dirfd,
const char *pathname,
int flags, mode_t mode)
2646 File *cwd = check_dirfd(dirfd);
2653 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
2654 PosixSubsystem::SafeRead))
2656 F_NOTICE(
"open -> invalid address");
2657 SYSCALL_ERROR(InvalidArgument);
2662 "openat(" << dirfd <<
", " << pathname <<
", " << flags <<
", " <<
Oct 2672 F_NOTICE(
" -> No subsystem for this process!");
2677 if (!(CHECK_FLAG(flags, O_RDONLY) || CHECK_FLAG(flags, O_RDWR) ||
2678 CHECK_FLAG(flags, O_WRONLY)))
2680 F_NOTICE(
"One of O_RDONLY, O_WRONLY, or O_RDWR must be passed.");
2681 SYSCALL_ERROR(InvalidArgument);
2686 if (pathname[0] == 0)
2688 F_NOTICE(
" -> File does not exist (null path).");
2689 SYSCALL_ERROR(DoesNotExist);
2696 mode &= ~pPosixProcess->getMask();
2699 size_t fd = pSubsystem->
getFd();
2703 bool onDevFs =
false;
2704 bool openingCtty =
false;
2706 normalisePath(nameToOpen, pathname, &onDevFs);
2707 if (nameToOpen ==
"/dev/tty")
2714 F_NOTICE(
" -> returning -1, no controlling tty");
2717 else if (ConsoleManager::instance().isMasterConsole(file))
2720 F_NOTICE(
" -> controlling terminal was not a slave");
2721 file = ConsoleManager::instance().getOther(file);
2725 F_NOTICE(
" -> actual filename to open is '" << nameToOpen <<
"'");
2730 file = findFileWithAbiFallbacks(nameToOpen, cwd);
2733 bool bCreated =
false;
2736 if ((flags & O_CREAT) && !onDevFs)
2738 F_NOTICE(
" {O_CREAT}");
2743 F_NOTICE(
" -> File does not exist (createFile failed)");
2748 file = findFileWithAbiFallbacks(nameToOpen, cwd);
2751 F_NOTICE(
" -> File does not exist (O_CREAT failed)");
2752 SYSCALL_ERROR(DoesNotExist);
2761 F_NOTICE(
" -> Does not exist.");
2763 SYSCALL_ERROR(DoesNotExist);
2771 F_NOTICE(
" -> File does not exist.");
2772 SYSCALL_ERROR(DoesNotExist);
2777 file = traverseSymlink(file);
2781 SYSCALL_ERROR(DoesNotExist);
2786 if (file->
isDirectory() && (flags & (O_WRONLY | O_RDWR)))
2789 F_NOTICE(
" -> Is a directory, and O_WRONLY or O_RDWR was specified.");
2790 SYSCALL_ERROR(IsADirectory);
2795 if ((flags & O_CREAT) && (flags & O_EXCL) && !bCreated)
2798 F_NOTICE(
" -> File exists");
2799 SYSCALL_ERROR(FileExists);
2805 bool checkRead = (flags == O_RDONLY) || (flags & O_RDWR);
2817 file, checkRead, flags & (O_WRONLY | O_RDWR | O_TRUNC),
false))
2820 F_NOTICE(
" -> file access denied.");
2824 if ((newFile != file) &&
2826 newFile, checkRead, flags & (O_WRONLY | O_RDWR | O_TRUNC),
2830 F_NOTICE(
" -> file access denied.");
2839 if (ConsoleManager::instance().isConsole(file))
2842 if (ConsoleManager::instance().isMasterConsole(file))
2846 if (!ConsoleManager::instance().lockConsole(file))
2848 F_NOTICE(
"Couldn't lock pseudoterminal master");
2849 SYSCALL_ERROR(DeviceBusy);
2857 if ((flags & O_NOCTTY) == 0 && !openingCtty)
2860 " -> setting opened terminal '" << file->
getName()
2861 <<
"' to be controlling");
2862 console_setctty(file,
false);
2868 if ((flags & O_TRUNC) &&
2869 ((flags & O_CREAT) || (flags & O_WRONLY) || (flags & O_RDWR)))
2871 F_NOTICE(
" -> {O_TRUNC}");
2879 F_NOTICE(
"FIFO => checking if we have any readers");
2884 if (!pipe->getReaderCount())
2886 F_NOTICE(
"FIFO => might need to wait for a reader");
2887 if (flags & O_WRONLY)
2890 if (flags & O_NONBLOCK)
2893 F_NOTICE(
" -> ENXIO");
2894 SYSCALL_ERROR(NoSuchDevice);
2900 F_NOTICE(
"FIFO => not a non-blocking open");
2903 if (!pipe->waitForReader())
2906 F_NOTICE(
" -> EINTR (fifo)");
2907 SYSCALL_ERROR(Interrupted);
2913 F_NOTICE(
"FIFO => successfully waited for a reader");
2920 F_NOTICE(
"FIFO => " << pipe->getReaderCount() <<
" readers.");
2925 file, (flags & O_APPEND) ? file->getSize() : 0, fd, 0, flags);
2929 F_NOTICE(
" -> " << fd);
2931 return static_cast<int>(fd);
2934 int posix_mkdirat(
int dirfd,
const char *pathname, mode_t mode)
2936 F_NOTICE(
"mkdirat");
2938 File *cwd = check_dirfd(dirfd);
2945 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
2946 PosixSubsystem::SafeRead))
2948 F_NOTICE(
"mkdirat -> invalid address");
2949 SYSCALL_ERROR(InvalidArgument);
2953 F_NOTICE(
"mkdirat(" << dirfd <<
", " << pathname <<
", " << mode <<
")");
2956 normalisePath(realPath, pathname);
2961 mode &= ~pPosixProcess->getMask();
2965 return worked ? 0 : -1;
2969 int dirfd,
const char *pathname, uid_t owner, gid_t group,
int flags)
2971 F_NOTICE(
"fchownat");
2973 File *cwd = check_dirfd(dirfd, flags);
2981 if (flags & AT_EMPTY_PATH)
2989 SYSCALL_ERROR(InvalidArgument);
2994 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
2995 PosixSubsystem::SafeRead))
2997 F_NOTICE(
"chown -> invalid address");
2998 SYSCALL_ERROR(InvalidArgument);
3003 "fchownat(" << dirfd <<
", " << pathname <<
", " << owner <<
", " 3004 << group <<
", " << flags <<
")");
3009 if ((owner == group) && (owner == static_cast<uid_t>(-1)))
3012 bool onDevFs =
false;
3014 normalisePath(realPath, pathname, &onDevFs);
3029 F_NOTICE(
" -> No subsystem for this process!");
3034 if ((flags & AT_EMPTY_PATH) && ((pathname == 0) || (*pathname == 0)))
3040 SYSCALL_ERROR(BadFileDescriptor);
3048 file = findFileWithAbiFallbacks(realPath, cwd);
3051 SYSCALL_ERROR(DoesNotExist);
3059 SYSCALL_ERROR(ReadOnlyFilesystem);
3064 if ((flags & AT_SYMLINK_NOFOLLOW) == 0)
3066 file = traverseSymlink(file);
3071 SYSCALL_ERROR(DoesNotExist);
3075 return doChown(file, owner, group) ? 0 : -1;
3078 int posix_futimesat(
3079 int dirfd,
const char *pathname,
const struct timeval *times)
3081 F_NOTICE(
"futimesat");
3083 File *cwd = check_dirfd(dirfd);
3090 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3091 PosixSubsystem::SafeRead) &&
3094 reinterpret_cast<uintptr_t>(times),
sizeof(
struct timeval) * 2,
3095 PosixSubsystem::SafeRead))))
3097 F_NOTICE(
"utimes -> invalid address");
3098 SYSCALL_ERROR(InvalidArgument);
3102 F_NOTICE(
"futimesat(" << dirfd <<
", " << pathname <<
", " << times <<
")");
3105 normalisePath(realPath, pathname);
3107 File *file = findFileWithAbiFallbacks(realPath, cwd);
3110 SYSCALL_ERROR(DoesNotExist);
3115 file = traverseSymlink(file);
3125 Time::Timestamp accessTime;
3126 Time::Timestamp modifyTime;
3129 struct timeval access = times[0];
3130 struct timeval modify = times[1];
3132 accessTime = access.tv_sec * Time::Multiplier::Second;
3133 accessTime += access.tv_usec * Time::Multiplier::Microsecond;
3135 modifyTime = modify.tv_sec * Time::Multiplier::Second;
3136 modifyTime += modify.tv_usec * Time::Multiplier::Microsecond;
3140 accessTime = modifyTime = Time::getTimeNanoseconds();
3149 int posix_unlinkat(
int dirfd,
const char *pathname,
int flags)
3151 F_NOTICE(
"unlinkat");
3153 File *cwd = check_dirfd(dirfd);
3160 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3161 PosixSubsystem::SafeRead))
3163 F_NOTICE(
"unlink -> invalid address");
3164 SYSCALL_ERROR(InvalidArgument);
3168 F_NOTICE(
"unlinkat(" << dirfd <<
", " << pathname <<
", " << flags <<
")");
3171 normalisePath(realPath, pathname);
3173 File *pFile = findFileWithAbiFallbacks(realPath, cwd);
3176 SYSCALL_ERROR(DoesNotExist);
3179 else if (pFile->
isDirectory() && ((flags & AT_REMOVEDIR) == 0))
3182 SYSCALL_ERROR(NotEnoughPermissions);
3198 int olddirfd,
const char *oldpath,
int newdirfd,
const char *newpath)
3200 F_NOTICE(
"renameat");
3202 File *oldcwd = check_dirfd(olddirfd);
3208 File *newcwd = check_dirfd(newdirfd);
3215 reinterpret_cast<uintptr_t>(oldpath), PATH_MAX,
3216 PosixSubsystem::SafeRead) &&
3218 reinterpret_cast<uintptr_t>(newpath), PATH_MAX,
3219 PosixSubsystem::SafeRead)))
3221 F_NOTICE(
"rename -> invalid address");
3222 SYSCALL_ERROR(InvalidArgument);
3227 "renameat(" << olddirfd <<
", " << oldpath <<
", " << newdirfd <<
", " 3232 normalisePath(realSource, oldpath);
3233 normalisePath(realDestination, newpath);
3235 File *src = findFileWithAbiFallbacks(realSource, oldcwd);
3236 File *dest = findFileWithAbiFallbacks(realDestination, newcwd);
3240 SYSCALL_ERROR(DoesNotExist);
3245 src = traverseSymlink(src);
3248 SYSCALL_ERROR(DoesNotExist);
3255 dest = traverseSymlink(dest);
3258 SYSCALL_ERROR(DoesNotExist);
3264 SYSCALL_ERROR(FileExists);
3269 SYSCALL_ERROR(NotADirectory);
3276 dest = findFileWithAbiFallbacks(realDestination, newcwd);
3285 uint8_t *buf =
new uint8_t[src->getSize()];
3286 src->
read(0, src->getSize(),
reinterpret_cast<uintptr_t
>(buf));
3288 dest->
write(0, src->getSize(),
reinterpret_cast<uintptr_t
>(buf));
3296 int olddirfd,
const char *oldpath,
int newdirfd,
const char *newpath,
3301 File *oldcwd = check_dirfd(olddirfd, flags);
3307 File *newcwd = check_dirfd(newdirfd);
3314 reinterpret_cast<uintptr_t>(oldpath), PATH_MAX,
3315 PosixSubsystem::SafeRead) &&
3317 reinterpret_cast<uintptr_t>(newpath), PATH_MAX,
3318 PosixSubsystem::SafeRead)))
3320 F_NOTICE(
"link -> invalid address");
3321 SYSCALL_ERROR(InvalidArgument);
3326 "linkat(" << olddirfd <<
", " << oldpath <<
", " << newdirfd <<
", " 3327 << newpath <<
", " << flags <<
")");
3336 ERROR(
"No subsystem for this process!");
3343 normalisePath(realTarget, oldpath);
3344 normalisePath(realLink, newpath);
3347 if ((flags & AT_EMPTY_PATH) && ((oldpath == 0) || (*oldpath == 0)))
3353 SYSCALL_ERROR(BadFileDescriptor);
3357 pTarget = pFd->
file;
3361 pTarget = findFileWithAbiFallbacks(realTarget, oldcwd);
3364 if (flags & AT_SYMLINK_FOLLOW)
3366 pTarget = traverseSymlink(pTarget);
3371 F_NOTICE(
" -> target '" << realTarget <<
"' did not exist.");
3372 SYSCALL_ERROR(DoesNotExist);
3380 F_NOTICE(
" -> failed to create link");
3388 int posix_symlinkat(
const char *oldpath,
int newdirfd,
const char *newpath)
3390 F_NOTICE(
"symlinkat");
3392 File *cwd = check_dirfd(newdirfd);
3399 reinterpret_cast<uintptr_t>(oldpath), PATH_MAX,
3400 PosixSubsystem::SafeRead) &&
3402 reinterpret_cast<uintptr_t>(newpath), PATH_MAX,
3403 PosixSubsystem::SafeRead)))
3405 F_NOTICE(
"symlink -> invalid address");
3406 SYSCALL_ERROR(InvalidArgument);
3411 "symlinkat(" << oldpath <<
", " << newdirfd <<
", " << newpath <<
")");
3418 ERROR(
"Symlink failed for `" << newpath <<
"' -> `" << oldpath <<
"'");
3422 int posix_readlinkat(
int dirfd,
const char *pathname,
char *buf,
size_t bufsiz)
3424 F_NOTICE(
"readlinkat");
3426 File *cwd = check_dirfd(dirfd);
3433 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3434 PosixSubsystem::SafeRead) &&
3436 reinterpret_cast<uintptr_t>(buf), bufsiz,
3437 PosixSubsystem::SafeWrite)))
3439 F_NOTICE(
"readlink -> invalid address");
3440 SYSCALL_ERROR(InvalidArgument);
3445 "readlinkat(" << dirfd <<
", " << pathname <<
", " << buf <<
", " 3449 normalisePath(realPath, pathname);
3451 File *f = findFileWithAbiFallbacks(realPath, cwd);
3454 SYSCALL_ERROR(DoesNotExist);
3460 SYSCALL_ERROR(InvalidArgument);
3475 int posix_fchmodat(
int dirfd,
const char *pathname, mode_t mode,
int flags)
3477 F_NOTICE(
"fchmodat");
3479 File *cwd = check_dirfd(dirfd, flags);
3487 if (flags & AT_EMPTY_PATH)
3495 SYSCALL_ERROR(InvalidArgument);
3500 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3501 PosixSubsystem::SafeRead))
3503 F_NOTICE(
"chmod -> invalid address");
3504 SYSCALL_ERROR(InvalidArgument);
3509 "fchmodat(" << dirfd <<
", " << pathname <<
", " <<
Oct << mode <<
Hex 3510 <<
", " << flags <<
")");
3512 if (mode == static_cast<mode_t>(-1))
3514 F_NOTICE(
" -> invalid mode");
3515 SYSCALL_ERROR(InvalidArgument);
3519 bool onDevFs =
false;
3521 normalisePath(realPath, pathname, &onDevFs);
3536 F_NOTICE(
" -> No subsystem for this process!");
3542 if ((flags & AT_EMPTY_PATH) && ((pathname == 0) || (*pathname == 0)))
3548 SYSCALL_ERROR(BadFileDescriptor);
3556 file = findFileWithAbiFallbacks(realPath, GET_CWD());
3559 SYSCALL_ERROR(DoesNotExist);
3567 SYSCALL_ERROR(ReadOnlyFilesystem);
3572 if ((flags & AT_SYMLINK_NOFOLLOW) == 0)
3574 file = traverseSymlink(file);
3579 SYSCALL_ERROR(DoesNotExist);
3583 return doChmod(file, mode) ? 0 : -1;
3586 int posix_faccessat(
int dirfd,
const char *pathname,
int mode,
int flags)
3588 F_NOTICE(
"faccessat");
3590 File *cwd = check_dirfd(dirfd);
3597 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3598 PosixSubsystem::SafeRead))
3600 F_NOTICE(
"access -> invalid address");
3601 SYSCALL_ERROR(InvalidArgument);
3606 "faccessat(" << dirfd <<
", " << pathname <<
", " << mode <<
", " 3611 SYSCALL_ERROR(DoesNotExist);
3616 normalisePath(realPath, pathname);
3619 File *file = findFileWithAbiFallbacks(realPath, cwd);
3621 if ((flags & AT_SYMLINK_NOFOLLOW) == 0)
3623 file = traverseSymlink(file);
3628 F_NOTICE(
" -> '" << realPath <<
"' does not exist");
3629 SYSCALL_ERROR(DoesNotExist);
3643 F_NOTICE(
" -> not ok");
3651 int posix_fstatat(
int dirfd,
const char *pathname,
struct stat *buf,
int flags)
3653 F_NOTICE(
"fstatat");
3655 File *cwd = check_dirfd(dirfd, flags);
3658 F_NOTICE(
" -> current working directory could not be determined");
3664 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3665 PosixSubsystem::SafeRead) &&
3667 reinterpret_cast<uintptr_t>(buf),
3668 sizeof(
struct stat), PosixSubsystem::SafeWrite))))
3670 F_NOTICE(
"fstat -> invalid address");
3671 SYSCALL_ERROR(InvalidArgument);
3676 "fstatat(" << dirfd <<
", " << (pathname ? pathname :
"(n/a)") <<
", " 3677 << buf <<
", " << flags <<
")");
3683 SYSCALL_ERROR(InvalidArgument);
3694 ERROR(
"No subsystem for this process!");
3700 if ((flags & AT_EMPTY_PATH) && ((pathname == 0) || (*pathname == 0)))
3706 SYSCALL_ERROR(BadFileDescriptor);
3715 normalisePath(realPath, pathname);
3718 " -> finding file with real path " << realPath <<
" in " 3721 file = findFileWithAbiFallbacks(realPath, cwd);
3724 SYSCALL_ERROR(DoesNotExist);
3725 F_NOTICE(
" -> unable to find '" << realPath <<
"' here");
3730 if ((flags & AT_SYMLINK_NOFOLLOW) == 0)
3732 file = traverseSymlink(file);
3737 SYSCALL_ERROR(DoesNotExist);
3741 if (!doStat(0, file, buf))
3746 F_NOTICE(
" -> Success");
3751 static ssize_t doGetXattr(
3752 const char *filepath,
int fd,
const char *name,
void *value,
size_t size,
3756 SYSCALL_ERROR(OperationNotSupported);
3761 posix_getxattr(
const char *path,
const char *name,
void *value,
size_t size)
3763 return doGetXattr(path, -1, name, value, size,
true);
3767 posix_lgetxattr(
const char *path,
const char *name,
void *value,
size_t size)
3769 return doGetXattr(path, -1, name, value, size,
false);
3772 ssize_t posix_fgetxattr(
int fd,
const char *name,
void *value,
size_t size)
3774 return doGetXattr(
nullptr, fd, name, value, size,
true);
3777 int posix_mknod(
const char *pathname, mode_t mode, dev_t dev)
3781 reinterpret_cast<uintptr_t>(pathname), PATH_MAX,
3782 PosixSubsystem::SafeRead))
3784 F_NOTICE(
" -> invalid address for pathname");
3785 SYSCALL_ERROR(InvalidArgument);
3789 F_NOTICE(
"mknod(" << pathname <<
", " << mode <<
", " << dev <<
")");
3791 File *targetFile = findFileWithAbiFallbacks(
String(pathname), GET_CWD());
3794 F_NOTICE(
" -> already exists");
3795 SYSCALL_ERROR(FileExists);
3800 const char *parentDirectory = DirectoryName(pathname);
3801 const char *baseName = BaseName(pathname);
3804 F_NOTICE(
" -> no filename provided");
3805 SYSCALL_ERROR(DoesNotExist);
3806 delete[] parentDirectory;
3814 File *parentFile = GET_CWD();
3815 if (parentDirectory)
3818 normalisePath(parentPath, parentDirectory,
nullptr);
3819 F_NOTICE(
"finding parent directory " << parentDirectory <<
"...");
3820 F_NOTICE(
" -> " << parentPath <<
"...");
3821 parentFile = findFileWithAbiFallbacks(parentPath, GET_CWD());
3823 parentFile = traverseSymlink(parentFile);
3827 F_NOTICE(
" -> symlink traversal failed");
3833 NOTICE(
"NO parent directory was found for path " << pathname);
3838 SYSCALL_ERROR(NotADirectory);
3839 F_NOTICE(
" -> target parent is not a directory");
3845 if ((mode & S_IFIFO) == S_IFIFO)
3849 String(baseName), 0, 0, 0, 0, parentDir->getFilesystem(), 0,
3853 F_NOTICE(
" -> fifo/pipe '" << baseName <<
"' created!");
3854 F_NOTICE(
" -> full path is " << pipe->
getFullPath(
true));
3858 SYSCALL_ERROR(Unimplemented);
3859 F_NOTICE(
" -> unimplemented mode requested");
3866 static int do_statfs(
File *file,
struct statfs *buf)
3869 reinterpret_cast<uintptr_t>(buf),
sizeof(
struct statfs),
3870 PosixSubsystem::SafeWrite))
3872 F_NOTICE(
" -> invalid address for buf [" << buf <<
"]");
3873 SYSCALL_ERROR(InvalidArgument);
3879 F_NOTICE(
" -> file does not exist");
3880 SYSCALL_ERROR(DoesNotExist);
3887 bool bFilled =
false;
3888 if (pFs == g_pDevFs)
3890 F_NOTICE(
" -> file '" << file->
getName() <<
"' is on devfs");
3895 F_NOTICE(
" -> filling statfs struct with /dev/pts data");
3896 ByteSet(buf, 0,
sizeof(*buf));
3897 buf->f_type = 0x1CD1;
3898 buf->f_bsize = 4096;
3899 buf->f_namelen = PATH_MAX;
3900 buf->f_frsize = 4096;
3908 F_NOTICE(
" -> filling statfs struct with ext2 data");
3909 ByteSet(buf, 0,
sizeof(*buf));
3910 buf->f_type = 0xEF53;
3919 buf->f_bsize = 4096;
3920 buf->f_blocks = 0x100000;
3922 buf->f_bfree = buf->f_blocks;
3923 buf->f_bavail = buf->f_blocks;
3924 buf->f_files = 1234;
3925 buf->f_ffree = 5678;
3926 buf->f_namelen = PATH_MAX;
3934 int posix_statfs(
const char *path,
struct statfs *buf)
3939 reinterpret_cast<uintptr_t>(path), PATH_MAX,
3940 PosixSubsystem::SafeRead))
3942 F_NOTICE(
" -> invalid address for path");
3943 SYSCALL_ERROR(InvalidArgument);
3947 F_NOTICE(
"statfs(" << path <<
")");
3949 normalisePath(normalisedPath, path);
3950 F_NOTICE(
" -> actually performing statfs on " << normalisedPath);
3951 File *file = findFileWithAbiFallbacks(normalisedPath, GET_CWD());
3953 return do_statfs(file, buf);
3956 int posix_fstatfs(
int fd,
struct statfs *buf)
3958 F_NOTICE(
"fstatfs(" << fd <<
")");
3966 ERROR(
"No subsystem for this process!");
3974 SYSCALL_ERROR(BadFileDescriptor);
3978 return do_statfs(pFd->
file, buf);
3982 const char *src,
const char *tgt,
const char *fs,
size_t flags,
3988 reinterpret_cast<uintptr_t>(src), PATH_MAX,
3989 PosixSubsystem::SafeRead) &&
3991 reinterpret_cast<uintptr_t>(tgt), PATH_MAX,
3992 PosixSubsystem::SafeRead) &&
3994 reinterpret_cast<uintptr_t>(fs), PATH_MAX,
3995 PosixSubsystem::SafeRead)))
3997 F_NOTICE(
" -> invalid address");
3998 SYSCALL_ERROR(BadAddress);
4007 "mount(" << source <<
", " << target <<
", " << fstype <<
", " <<
Hex 4008 << flags <<
", " << data <<
")");
4012 normalisePath(targetNormalised, tgt);
4013 File *targetFile = findFileWithAbiFallbacks(targetNormalised,
nullptr);
4016 F_NOTICE(
" -> target does not exist");
4017 SYSCALL_ERROR(DoesNotExist);
4023 F_NOTICE(
" -> target not a directory");
4024 SYSCALL_ERROR(NotADirectory);
4031 if (fstype ==
"proc")
4033 F_NOTICE(
" -> adding another procfs mount");
4038 SYSCALL_ERROR(DeviceDoesNotExist);
4042 if (targetFile == pFs->
getRoot() ||
4053 else if (fstype ==
"tmpfs")
4055 F_NOTICE(
" -> creating new tmpfs");
4065 F_NOTICE(
" -> unsupported fstype");
4066 SYSCALL_ERROR(DeviceDoesNotExist);
4070 SYSCALL_ERROR(PermissionDenied);
4074 void generate_mtab(
String &result)
4078 struct Remapping *remap = g_Remappings;
4079 while (remap->from !=
nullptr)
4085 "%s %s %s rw 0 0\n", remap->to, remap->from, remap->fsname);
4100 line.Format(
"/dev/sda1 / ext2 rw 0 0\n");
4105 F_NOTICE(
"generated mtab:\n" << result);
void unlockConsole(File *file)
Release a console master locked as above.
void removeWakeupWatcher(WakeReason *watcher)
uint64_t offset
Offset within the file for I/O.
void activate(size_t n)
Starts the process of activating the given tty.
virtual bool isFifo() const
virtual Keyboard * getKeyboard()=0
void addWakeupWatcher(WakeReason *watcher)
virtual int command(const size_t command, void *buffer)
static size_t getPageSize() PURE
virtual bool initialise(Disk *pDisk)
void reportPermission(SwitchPermission perm)
Time::Timestamp getAccessedTime()
virtual int select(bool bWriting=false, int timeout=0)
void freeFd(size_t fdNum)
bool createLink(const String &path, File *target, File *pStartNode=0)
virtual void getName(String &str)
int followLink(char *pBuffer, size_t bufLen)
struct vt_mode getTerminalMode(size_t n) const
void monitor(Thread *pThread, Event *pEvent)
MemoryMappedObject * mapAnon(uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms)
Tree< Filesystem *, List< String * > * > & getMounts()
SharedPointer< class NetworkSyscalls > networkImpl
Network syscall implementation for this descriptor (if it's a socket).
virtual uintptr_t getUserStart() const =0
virtual bool supports(const size_t command) const
virtual void setLedState(char state)
virtual size_t getBlockSize() const
static Directory * fromFile(File *pF)
static KeymapManager & instance()
Singleton design.
void setReparsePoint(Directory *pTarget)
Filesystem * lookupFilesystem(const String &alias)
virtual uintptr_t getKernelStart() const =0
static ProcessorInformation & information()
void addFileDescriptor(size_t fd, FileDescriptor *pFd)
File * file
Our open file pointer.
Group * getGroup(size_t id)
Time::Timestamp getCreationTime()
virtual File * getRoot() const
size_t setPermissions(uintptr_t base, size_t length, MemoryMappedObject::Permissions perms)
uint8_t convertPc102ScancodeToHidKeycode(uint8_t scancode, EscapeState &escape)
Converts a pc102 scancode into a HID keycode.
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
void invalidate(uintptr_t base, size_t length)
bool createSymlink(const String &path, const String &value, File *pStartNode=0)
void sync(uintptr_t base, size_t length, bool async)
void insert(const K &key, const E &value)
virtual size_t getSize() const
Gets the size of the disk.
Memory-mapped file interface.
virtual size_t getBlockSize() const
Gets the block size of the disk.
bool isMember(User *pUser)
virtual String getFullPath(bool bWithLabel=true)
int flflags
File status flags (fcntl)
static MemoryMapManager & instance()
bool createDirectory(const String &path, uint32_t mask, File *pStartNode=0)
void setRootFile(File *pFile)
bool createFile(const String &path, uint32_t mask, File *pStartNode=0)
void setModifiedTime(Time::Timestamp t)
virtual char getLedState()
MemoryMappedObject * mapFile(File *pFile, uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms, size_t offset=0, bool bCopyOnWrite=true)
bool remove(const String &path, File *pStartNode=0)
virtual bool isSocket() const
virtual bool isPipe() const
void setTerminalMode(size_t n, struct vt_mode mode)
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
static Symlink * fromFile(File *pF)
KeymapEntry * getKeymapEntry(bool bCtrl, bool bShift, bool bAlt, bool bAltGr, uint8_t nCombinator, uint8_t keyCode)
Returns the keymap entry corresponding to given keycode and modifiers.
Process * getParent() const
Time::Timestamp getModifiedTime()
virtual void getName(String &str)
int fdflags
File descriptor flags (fcntl)
virtual ProcessType getType()
bool addEphemeralFile(File *pFile)
Add an ephemeral file to the directory.
IoEvent * ioevent
IO event for reporting changes to files.
void setInterrupted(bool b)
static UserManager & instance()
FileDescriptor * getFileDescriptor(size_t fd)
virtual bool isDirectory()
File * getChild(size_t n)
Directory * getReparsePoint() const
Get the reparse point attached to this directory. Reparse points allow locations on the filesystem to...
size_t remove(uintptr_t base, size_t length)
virtual File * findFile(const String &path, File *workingDir)
Device * getParent() const
E lookup(const K &key) const
static Pipe * fromFile(File *pF)
void setAccessedTime(Time::Timestamp t)
Structure representing an entry in the keymap table.
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
virtual void threadException(Thread *pThread, ExceptionType eType)
virtual File * getRoot() const =0