#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IOBUF_SIZE 4096 /* copy_path - copy path name */ static int copy_path(char **to, const char *from) { struct mm_struct *mm = current->mm; char *buffer; if ((buffer = kmalloc(FS_MAX_FPATH_LEN + 1)) == NULL) { return -E_NO_MEM; } lock_mm(mm); if (!copy_string(mm, buffer, from, FS_MAX_FPATH_LEN + 1)) { unlock_mm(mm); goto failed_cleanup; } unlock_mm(mm); *to = buffer; return 0; failed_cleanup: kfree(buffer); return -E_INVAL; } /* sysfile_open - open file */ int sysfile_open(const char *__path, uint32_t open_flags) { int ret; char *path; if ((ret = copy_path(&path, __path)) != 0) { return ret; } ret = file_open(path, open_flags); kfree(path); return ret; } /* sysfile_close - close file */ int sysfile_close(int fd) { return file_close(fd); } /* sysfile_read - read file */ int sysfile_read(int fd, void *base, size_t len) { struct mm_struct *mm = current->mm; if (len == 0) { return 0; } if (!file_testfd(fd, 1, 0)) { return -E_INVAL; } void *buffer; if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) { return -E_NO_MEM; } int ret = 0; size_t copied = 0, alen; while (len != 0) { if ((alen = IOBUF_SIZE) > len) { alen = len; } ret = file_read(fd, buffer, alen, &alen); if (alen != 0) { lock_mm(mm); { if (copy_to_user(mm, base, buffer, alen)) { assert(len >= alen); base += alen, len -= alen, copied += alen; } else if (ret == 0) { ret = -E_INVAL; } } unlock_mm(mm); } if (ret != 0 || alen == 0) { goto out; } } out: kfree(buffer); if (copied != 0) { return copied; } return ret; } /* sysfile_write - write file */ int sysfile_write(int fd, void *base, size_t len) { struct mm_struct *mm = current->mm; if (len == 0) { return 0; } if (!file_testfd(fd, 0, 1)) { return -E_INVAL; } void *buffer; if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) { return -E_NO_MEM; } int ret = 0; size_t copied = 0, alen; while (len != 0) { if ((alen = IOBUF_SIZE) > len) { alen = len; } lock_mm(mm); { if (!copy_from_user(mm, buffer, base, alen, 0)) { ret = -E_INVAL; } } unlock_mm(mm); if (ret == 0) { ret = file_write(fd, buffer, alen, &alen); if (alen != 0) { assert(len >= alen); base += alen, len -= alen, copied += alen; } } if (ret != 0 || alen == 0) { goto out; } } out: kfree(buffer); if (copied != 0) { return copied; } return ret; } /* sysfile_seek - seek file */ int sysfile_seek(int fd, off_t pos, int whence) { return file_seek(fd, pos, whence); } /* sysfile_fstat - stat file */ int sysfile_fstat(int fd, struct stat *__stat) { struct mm_struct *mm = current->mm; int ret; struct stat __local_stat, *stat = &__local_stat; if ((ret = file_fstat(fd, stat)) != 0) { return ret; } lock_mm(mm); { if (!copy_to_user(mm, __stat, stat, sizeof(struct stat))) { ret = -E_INVAL; } } unlock_mm(mm); return ret; } /* sysfile_fsync - sync file */ int sysfile_fsync(int fd) { return file_fsync(fd); } /* sysfile_chdir - change dir */ int sysfile_chdir(const char *__path) { int ret; char *path; if ((ret = copy_path(&path, __path)) != 0) { return ret; } ret = vfs_chdir(path); kfree(path); return ret; } /* sysfile_link - link file */ int sysfile_link(const char *__path1, const char *__path2) { int ret; char *old_path, *new_path; if ((ret = copy_path(&old_path, __path1)) != 0) { return ret; } if ((ret = copy_path(&new_path, __path2)) != 0) { kfree(old_path); return ret; } ret = vfs_link(old_path, new_path); kfree(old_path), kfree(new_path); return ret; } /* sysfile_rename - rename file */ int sysfile_rename(const char *__path1, const char *__path2) { int ret; char *old_path, *new_path; if ((ret = copy_path(&old_path, __path1)) != 0) { return ret; } if ((ret = copy_path(&new_path, __path2)) != 0) { kfree(old_path); return ret; } ret = vfs_rename(old_path, new_path); kfree(old_path), kfree(new_path); return ret; } /* sysfile_unlink - unlink file */ int sysfile_unlink(const char *__path) { int ret; char *path; if ((ret = copy_path(&path, __path)) != 0) { return ret; } ret = vfs_unlink(path); kfree(path); return ret; } /* sysfile_get cwd - get current working directory */ int sysfile_getcwd(char *buf, size_t len) { struct mm_struct *mm = current->mm; if (len == 0) { return -E_INVAL; } int ret = -E_INVAL; lock_mm(mm); { if (user_mem_check(mm, (uintptr_t)buf, len, 1)) { struct iobuf __iob, *iob = iobuf_init(&__iob, buf, len, 0); ret = vfs_getcwd(iob); } } unlock_mm(mm); return ret; } /* sysfile_getdirentry - get the file entry in DIR */ int sysfile_getdirentry(int fd, struct dirent *__direntp) { struct mm_struct *mm = current->mm; struct dirent *direntp; if ((direntp = kmalloc(sizeof(struct dirent))) == NULL) { return -E_NO_MEM; } int ret = 0; lock_mm(mm); { if (!copy_from_user(mm, &(direntp->offset), &(__direntp->offset), sizeof(direntp->offset), 1)) { ret = -E_INVAL; } } unlock_mm(mm); if (ret != 0 || (ret = file_getdirentry(fd, direntp)) != 0) { goto out; } lock_mm(mm); { if (!copy_to_user(mm, __direntp, direntp, sizeof(struct dirent))) { ret = -E_INVAL; } } unlock_mm(mm); out: kfree(direntp); return ret; } /* sysfile_dup - duplicate fd1 to fd2 */ int sysfile_dup(int fd1, int fd2) { return file_dup(fd1, fd2); } int sysfile_pipe(int *fd_store) { return -E_UNIMP; } int sysfile_mkfifo(const char *__name, uint32_t open_flags) { return -E_UNIMP; }