from . import syscall as syscall import string # Linux x86-64 open flags. The kernel translates these to FatFs FA_* modes; # never pass FatFs values from user space. define O_RDONLY = 0 define O_WRONLY = 1 define O_RDWR = 2 define O_CREAT = 64 define O_EXCL = 128 define O_TRUNC = 512 define O_APPEND = 1024 define O_DIRECTORY = 65536 define O_CLOEXEC = 524288 define SEEK_SET = 0 define SEEK_CUR = 1 define SEEK_END = 2 define DT_UNKNOWN = 0 define DT_REG = 8 define DT_DIR = 4 define DT_FILE = 8 # legacy alias def open(path: const str, flags: uint32) -> int: """SDK open() goes through openat(AT_FDCWD) so relative paths honor cwd.""" return syscall.openat(syscall.AT_FDCWD, path, flags, 0) def close(fd: int) -> int: return int(syscall._syscall1(uint64(syscall.Syscall.CLOSE), uint64(fd))) def read(fd: int, buf: rawptr, count: uint32) -> int: return int(syscall._syscall3(uint64(syscall.Syscall.READ), uint64(fd), uint64(buf), uint64(count))) def write(fd: int, buf: rawptr, count: uint32) -> int: return int(syscall._syscall3(uint64(syscall.Syscall.WRITE), uint64(fd), uint64(buf), uint64(count))) def seek(fd: int, offset: uint32, whence: uint32 = 0) -> int: """lseek: returns the new offset (>= 0) or -errno.""" return int(syscall._syscall3(uint64(syscall.Syscall.SEEK), uint64(fd), uint64(offset), uint64(whence))) def tell(fd: int) -> int: """当前偏移 = lseek(fd, 0, SEEK_CUR)。""" return int(syscall._syscall3(uint64(syscall.Syscall.SEEK), uint64(fd), 0, uint64(SEEK_CUR))) def fsize(fd: int) -> int: """文件大小 = lseek(fd, 0, SEEK_END),随后恢复原位置。""" cur: int = tell(fd) end: int = int(syscall._syscall3(uint64(syscall.Syscall.SEEK), uint64(fd), 0, uint64(SEEK_END))) if cur >= 0: syscall._syscall3(uint64(syscall.Syscall.SEEK), uint64(fd), uint64(cur), uint64(SEEK_SET)) return end def mkdir(path: const str) -> int: return int(syscall._syscall3(uint64(syscall.Syscall.MKDIR), uint64(path), 0, 0)) def remove(path: const str) -> int: return int(syscall._syscall3(uint64(syscall.Syscall.REMOVE), uint64(path), 0, 0)) def opendir(path: const str) -> int: """Linux opendir: openat(O_RDONLY|O_DIRECTORY), returns a fd.""" return syscall.openat(syscall.AT_FDCWD, path, O_RDONLY | O_DIRECTORY, 0) def readdir(fd: int, info: rawptr) -> int: """Fill the legacy fileinfo layout from one getdents64 record. Returns 0 with an entry, -ENOENT at end-of-directory, or another -errno. """ if info is None: return -22 # -EINVAL buf: [512]char n: int = syscall.getdents64(fd, &buf[0], uint64(512)) if n < 0: return n if n == 0: return -2 # -ENOENT: end of directory string.memset(info, 0, 288) # sizeof(fileinfo) dt: int = int(uint8(buf[18])) attr: uint8 = 0x20 if dt == DT_DIR: attr = 0x10 ap: uint8* = uint8*(uint64(info) + 4) ap[0] = attr dst: char* = char*(uint64(info) + 16) string.strcpy(dst, &buf[19]) return 0 def closedir(fd: int) -> int: return close(fd) def openat(dirfd: int, path: const str, flags: uint32, mode: uint32 = 0) -> int: return syscall.openat(dirfd, path, flags, mode) def rename(old_path: const str, new_path: const str) -> int: return syscall.rename(old_path, new_path) def rmdir(path: const str) -> int: return syscall.rmdir(path) def unlinkat(dirfd: int, path: const str, flags: uint32 = 0) -> int: return syscall.unlinkat(dirfd, path, flags) def fcntl(fd: int, cmd: uint32, arg: uint64 = 0) -> int: return syscall.fcntl(fd, cmd, arg) def stat(path: const str, info: rawptr) -> int: return int(syscall._syscall3(uint64(syscall.Syscall.STAT), uint64(path), uint64(info), 0)) def ioctl(fd: int, request: uint32, arg: rawptr) -> int: """设备控制(Linux ioctl 子集)。当前只有 devfs 设备(如 /dev/fb0)实现了它。""" return int(syscall._syscall3(uint64(syscall.Syscall.IOCTL), uint64(fd), uint64(request), uint64(arg))) class FileIO: _fd: int _pos: uint32 _size: uint32 _flags: uint32 _closed: int def __init__(self, fd: int, flags: uint32): self._fd = fd self._flags = flags self._pos = 0 sz: int = fsize(fd) if sz < 0: sz = 0 self._size = uint32(sz) self._closed = 0 def read(self, buf: rawptr, count: uint32) -> int: if self._closed: return -1 n: int = read(self._fd, buf, count) if n > 0: self._pos = self._pos + uint32(n) return n def write(self, buf: rawptr, count: uint32) -> int: if self._closed: return -1 n: int = write(self._fd, buf, count) if n > 0: self._pos = self._pos + uint32(n) if self._pos > self._size: self._size = self._pos return n def seek(self, offset: uint32) -> int: if self._closed: return -1 res: int = seek(self._fd, offset) if res >= 0: self._pos = uint32(res) return res def tell(self) -> uint32: return self._pos def size(self) -> uint32: return self._size def close(self) -> int: if self._closed: return 0 self._closed = 1 return close(self._fd) def is_closed(self) -> int: return self._closed class DirIO: _dd: int _closed: int def __init__(self, dd: int): self._dd = dd self._closed = 0 def read(self, info: rawptr) -> int: if self._closed: return -1 return readdir(self._dd, info) def close(self) -> int: if self._closed: return 0 self._closed = 1 return closedir(self._dd) def is_closed(self) -> int: return self._closed def open_file(path: const str, flags: uint32) -> FileIO: fd: int = open(path, flags) if fd < 0: return None return FileIO(fd, flags) def open_dir(path: const str) -> DirIO: dd: int = opendir(path) if dd < 0: return None return DirIO(dd)