static int sys_statf(char * file, uintptr_t st) { int result; PTR_VALIDATE(file); PTR_VALIDATE(st); fs_node_t * fn = kopen(file, 0); result = stat_node(fn, st); if (fn) close_fs(fn); return result; }
static int sys_execve(const char * filename, char *const argv[], char *const envp[]) { PTR_VALIDATE(argv); PTR_VALIDATE(filename); PTR_VALIDATE(envp); if (args_present("traceexec")) { debug_print(WARNING, "%d = exec(%s", current_process->id, filename); for (char * const * arg = argv; *arg; ++arg) { debug_print(WARNING, " %s", *arg); } debug_print(WARNING, " )"); } int argc = 0; int envc = 0; while (argv[argc]) { PTR_VALIDATE(argv[argc]); ++argc; } if (envp) { while (envp[envc]) { PTR_VALIDATE(envp[envc]); ++envc; } } debug_print(INFO, "Allocating space for arguments..."); char ** argv_ = malloc(sizeof(char *) * (argc + 1)); for (int j = 0; j < argc; ++j) { argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char)); memcpy(argv_[j], argv[j], strlen(argv[j]) + 1); } argv_[argc] = 0; char ** envp_; if (envp && envc) { envp_ = malloc(sizeof(char *) * (envc + 1)); for (int j = 0; j < envc; ++j) { envp_[j] = malloc((strlen(envp[j]) + 1) * sizeof(char)); memcpy(envp_[j], envp[j], strlen(envp[j]) + 1); } envp_[envc] = 0; } else { envp_ = malloc(sizeof(char *)); envp_[0] = NULL; } debug_print(INFO,"Releasing all shmem regions..."); shm_release_all((process_t *)current_process); current_process->cmdline = argv_; debug_print(INFO,"Executing..."); /* Discard envp */ return exec((char *)filename, argc, (char **)argv_, (char **)envp_); }
static int sys_stat(int fd, uintptr_t st) { PTR_VALIDATE(st); if (FD_CHECK(fd)) { return stat_node(FD_ENTRY(fd), st); } return -1; }
static int sys_ioctl(int fd, int request, void * argp) { if (FD_CHECK(fd)) { PTR_VALIDATE(argp); return ioctl_fs(FD_ENTRY(fd), request, argp); } return -1; }
static int sys_access(const char * file, int flags) { PTR_VALIDATE(file); debug_print(INFO, "access(%s, 0x%x) from pid=%d", file, flags, getpid()); fs_node_t * node = kopen((char *)file, 0); if (!node) return -1; close_fs(node); return 0; }
static int sys_write(int fd, char * ptr, int len) { if (FD_CHECK(fd)) { PTR_VALIDATE(ptr); fs_node_t * node = FD_ENTRY(fd); uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr); node->offset += out; return out; } return -1; }
static int sys_chown(char * file, int uid, int gid) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { result = chown_fs(fn, uid, gid); close_fs(fn); return result; } else { return -1; } }
static int sys_chmod(char * file, int mode) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { result = chmod_fs(fn, mode); close_fs(fn); return result; } else { return -1; } }
static int sys_write(int fd, char * ptr, int len) { if (FD_CHECK(fd)) { PTR_VALIDATE(ptr); fs_node_t * node = FD_ENTRY(fd); if (!has_permission(node, 02)) { debug_print(WARNING, "access denied (write, fd=%d)", fd); return -EACCES; } uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr); node->offset += out; return out; } return -1; }
static int sys_write(int fd, char * ptr, int len) { if (FD_CHECK(fd)) { PTR_VALIDATE(ptr); fs_node_t * node = FD_ENTRY(fd); if (!(FD_MODE(fd) & 02)) { debug_print(WARNING, "access denied (write, fd=%d)", fd); return -EACCES; } uint32_t out = write_fs(node, FD_OFFSET(fd), len, (uint8_t *)ptr); FD_OFFSET(fd) += out; return out; } return -EBADF; }
static int stat_node(fs_node_t * fn, uintptr_t st) { struct stat * f = (struct stat *)st; PTR_VALIDATE(f); if (!fn) { memset(f, 0x00, sizeof(struct stat)); debug_print(INFO, "stat: This file doesn't exist"); return -1; } f->st_dev = 0; f->st_ino = fn->inode; uint32_t flags = 0; if (fn->flags & FS_FILE) { flags |= _IFREG; } if (fn->flags & FS_DIRECTORY) { flags |= _IFDIR; } if (fn->flags & FS_CHARDEVICE) { flags |= _IFCHR; } if (fn->flags & FS_BLOCKDEVICE) { flags |= _IFBLK; } if (fn->flags & FS_PIPE) { flags |= _IFIFO; } if (fn->flags & FS_SYMLINK) { flags |= _IFLNK; } f->st_mode = fn->mask | flags; f->st_nlink = fn->nlink; f->st_uid = fn->uid; f->st_gid = fn->gid; f->st_rdev = 0; f->st_size = fn->length; f->st_atime = fn->atime; f->st_mtime = fn->mtime; f->st_ctime = fn->ctime; if (fn->get_size) { f->st_size = fn->get_size(fn); } return 0; }
static int sys_readdir(int fd, int index, struct dirent * entry) { if (FD_CHECK(fd)) { PTR_VALIDATE(entry); struct dirent * kentry = readdir_fs(FD_ENTRY(fd), (uint32_t)index); if (kentry) { memcpy(entry, kentry, sizeof *entry); free(kentry); return 0; } else { return 1; } } return -1; }
static int sys_read(int fd, char * ptr, int len) { if (FD_CHECK(fd)) { PTR_VALIDATE(ptr); fs_node_t * node = FD_ENTRY(fd); if (!(FD_MODE(fd) & 01)) { debug_print(WARNING, "access denied (read, fd=%d, mode=%d, %s, %s)", fd, FD_MODE(fd), node->name, current_process->name); return -EACCES; } uint32_t out = read_fs(node, FD_OFFSET(fd), len, (uint8_t *)ptr); FD_OFFSET(fd) += out; return (int)out; } return -EBADF; }
static int sys_chmod(char * file, int mode) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { /* Can group members change bits? I think it's only owners. */ if (current_process->user != 0 && current_process->user != fn->uid) { close_fs(fn); return -EACCES; } result = chmod_fs(fn, mode); close_fs(fn); return result; } else { return -ENOENT; } }
static int sys_chown(char * file, int uid, int gid) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { /* TODO: Owners can change groups... */ if (current_process->user != 0) { close_fs(fn); return -EACCES; } result = chown_fs(fn, uid, gid); close_fs(fn); return result; } else { return -ENOENT; } }
static int sys_open(const char * file, int flags, int mode) { PTR_VALIDATE(file); debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode); fs_node_t * node = kopen((char *)file, flags); if (!node && (flags & O_CREAT)) { debug_print(NOTICE, "- file does not exist and create was requested."); /* Um, make one */ if (!create_file_fs((char *)file, mode)) { node = kopen((char *)file, flags); } } if (!node) { debug_print(NOTICE, "File does not exist; someone should be setting errno?"); return -1; } node->offset = 0; int fd = process_append_fd((process_t *)current_process, node); debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd); return fd; }
static int sys_open(const char * file, int flags, int mode) { PTR_VALIDATE(file); debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode); fs_node_t * node = kopen((char *)file, flags); if (node && !has_permission(node, 04)) { debug_print(WARNING, "access denied (read, sys_open, file=%s)", file); return -EACCES; } if (node && ((flags & O_RDWR) || (flags & O_APPEND) || (flags & O_WRONLY))) { if (!has_permission(node, 02)) { debug_print(WARNING, "access denied (write, sys_open, file=%s)", file); return -EACCES; } } if (!node && (flags & O_CREAT)) { /* TODO check directory permissions */ debug_print(NOTICE, "- file does not exist and create was requested."); /* Um, make one */ int result = create_file_fs((char *)file, mode); if (!result) { node = kopen((char *)file, flags); } else { return result; } } if (!node) { debug_print(NOTICE, "File does not exist; someone should be setting errno?"); return -1; } node->offset = 0; int fd = process_append_fd((process_t *)current_process, node); debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd); return fd; }
static int sys_open(const char * file, int flags, int mode) { PTR_VALIDATE(file); debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode); fs_node_t * node = kopen((char *)file, flags); int access_bits = 0; if (node && (flags & O_CREAT) && (flags & O_EXCL)) { close_fs(node); return -EEXIST; } if (!(flags & O_WRONLY) || (flags & O_RDWR)) { if (node && !has_permission(node, 04)) { debug_print(WARNING, "access denied (read, sys_open, file=%s)", file); close_fs(node); return -EACCES; } else { access_bits |= 01; } } if ((flags & O_RDWR) || (flags & O_WRONLY)) { if (node && !has_permission(node, 02)) { close_fs(node); return -EACCES; } if (node && (node->flags & FS_DIRECTORY)) { return -EISDIR; } if ((flags & O_RDWR) || (flags & O_WRONLY)) { /* truncate doesn't grant write permissions */ access_bits |= 02; } } if (!node && (flags & O_CREAT)) { /* TODO check directory permissions */ debug_print(NOTICE, "- file does not exist and create was requested."); /* Um, make one */ int result = create_file_fs((char *)file, mode); if (!result) { node = kopen((char *)file, flags); } else { return result; } } if (node && (flags & O_DIRECTORY)) { if (!(node->flags & FS_DIRECTORY)) { return -ENOTDIR; } } if (node && (flags & O_TRUNC)) { if (!(access_bits & 02)) { close_fs(node); return -EINVAL; } truncate_fs(node); } if (!node) { return -ENOENT; } if (node && (flags & O_CREAT) && (node->flags & FS_DIRECTORY)) { close_fs(node); return -EISDIR; } int fd = process_append_fd((process_t *)current_process, node); FD_MODE(fd) = access_bits; if (flags & O_APPEND) { FD_OFFSET(fd) = node->length; } else { FD_OFFSET(fd) = 0; } debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd); return fd; }