/* * @author xamidev * @brief File-related system calls * @license GPL-3.0-only */ #include #include #include #include #include #include #include extern struct process* current_process; /* * normalize_path - remove leading slashes from a path * @path: path to normalize * * Return: * %path - normalized path * %NULL - if bad argument */ static const char* normalize_path(const char* path) { if (!path) return NULL; while (*path == '/') { path++; } return path; } /* * sys_open - Open a file * @filename: Absolute path to file * @flags: (Not implemented) * * This system call opens a file in read-only mode, * because of the TAR filesystem. * * Return: * %fd - file descriptor refering to file * On error, a negative number representing the error code is returned. */ int sys_open(const char* filename, int flags) { // TODO: support flags (right now everything is read only, O_RDONLY) (void)flags; // gcc shut up const char* path = normalize_path(filename); if (tar_exists(path) < 0) { return -ENOENT; // file doesn't exist.. } // file exists here! if (current_process->next_free_fd >= FDT_MAX) { return -EMFILE; } int fd = current_process->next_free_fd++; current_process->fdt[fd].fd = fd; current_process->fdt[fd].open = true; current_process->fdt[fd].cursor = 0; strncpy(current_process->fdt[fd].filename, path, PROCESS_NAME_MAX - 1); return fd; } /* * sys_close - Close a file * @fd: file descriptor * * This system call closes the file referred to by * the file descriptor @fd. * * Return: * %0 - file closed * %-EBADFD - bad file descriptor */ int sys_close(unsigned int fd) { if (fd >= FDT_MAX) { return -EBADFD; } if (!current_process->fdt[fd].open) { return -EBADFD; // FD not opened in the first place } current_process->fdt[fd].open = false; current_process->fdt[fd].filename[0] = '\0'; current_process->fdt[fd].cursor = 0; return 0; } /* * sys_lseek - reposition file cursor * @fd: file descriptor referring to file * @offset: byte amount to be used according to @whence * @whence: resposition directive * * This system call repositions the cursor for @fd by @offset, * from somewhere in the file, depending on the value of @whence: * SEEK_SET (0) -> from the beginning * SEEK_CUR (1) -> from the actual value of the cursor * SEEK_END (2) -> from the end of the file * * Return: * %new_cursor - the new cursor value * On error, a negative value corresponding to an error code is returned. */ int sys_lseek(unsigned int fd, int offset, int whence) { if (fd >= FDT_MAX) { return -EBADFD; } if (!current_process->fdt[fd].open) { return -EBADFD; } int filesize = tar_exists(current_process->fdt[fd].filename); if (filesize < 0) { return -ENOENT; } int cursor = current_process->fdt[fd].cursor; int base; switch (whence) { case SEEK_SET: base = 0; break; case SEEK_CUR: base = cursor; break; case SEEK_END: base = filesize; break; default: return -EINVAL; } int new_cursor = base + offset; if (new_cursor < 0) new_cursor = 0; if (new_cursor > filesize) new_cursor = filesize; current_process->fdt[fd].cursor = new_cursor; return new_cursor; } /* * sys_tell - Get cursor position for a file * @fd: file descriptor to use * * Return: * %cursor - cursor position of the file descriptor * On error, a negative value with the corresponding error code is set. */ int sys_tell(unsigned int fd) { if (fd >= FDT_MAX) { return -EBADFD; } if (!current_process->fdt[fd].open) { return -EBADFD; } return current_process->fdt[fd].cursor; } /* * sys_eof - Are we at the end of the file yet? * @fd: file descriptor to use * * This function determines if the cursor for the * file descriptor @fd is at or past the end of * the file it refers to. * * Return: * %>0 - we are at or past EOF * %0 - not yet (still have bytes to read) */ int sys_eof(unsigned int fd) { if (fd >= FDT_MAX) { return -EBADFD; } if (!current_process->fdt[fd].open) { return -EBADFD; } int filesize = tar_exists(current_process->fdt[fd].filename); if (filesize < 0) { return -ENOENT; } return current_process->fdt[fd].cursor >= (uint64_t)filesize; } /* * sys_read - read from an open file * @fd: file descriptor to use * @buf: out buffer for read data * @count: amount of bytes to read * * Return: * %sz - amount of bytes read (on success) * On error, a negative value with an error code is returned. */ int sys_read(unsigned int fd, char* buf, size_t count) { size_t i; switch (fd) { case 0: //read from stdin (keyboard) for (i=0; ifdt[fd].open == false) { return -EBADFD; // File descriptor wasn't open } // Here fd refers to a valid opened file.. int sz = tar_read(current_process->fdt[fd].filename, buf, count, current_process->fdt[fd].cursor); if (sz == 0) { return -ENOENT; } else { current_process->fdt[fd].cursor += sz; return sz; } } return -EBADFD; } /* * sys_write - write to a file * @fd: file descriptor to write to * @buf: buffer of bytes to write * @count: number of bytes to write * * Return: * %count - number of bytes written * On error, a negative value with corresponding error code is returned. */ int sys_write(unsigned int fd, const char* buf, size_t count) { switch (fd) { case 1: //stdout case 2: //stderr for (size_t i=0; i