From beddff0f569d79109e45afd1cde91c4b254234de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 9 Aug 2002 20:20:28 +0000 Subject: [PATCH] Replaced opendir.c with directory.c, implemented chdir(), fchdir(), and getcwd(). Introduced new xyz(int fd, char *path, ...) style of functions for sys_setcwd(), and sys_write_stat(). Added missing sys_fstat(). Removed duplicated prototypes in syscalls.h Fixed some minor bugs. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@669 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/syscalls.h | 17 --- headers/posix/unistd.h | 6 +- headers/private/kernel/vfs.h | 15 +-- src/add-ons/kernel/file_systems/bfs/ToDo | 3 +- src/kernel/Jamfile | 8 +- src/kernel/apps/shell/commands.c | 23 ++-- src/kernel/core/fd.c | 34 ++++- src/kernel/core/fs/vfs.c | 153 ++++++++++++++--------- src/kernel/core/syscalls.c | 4 +- 9 files changed, 155 insertions(+), 108 deletions(-) diff --git a/headers/os/kernel/syscalls.h b/headers/os/kernel/syscalls.h index 68842a4cb3..71827b487f 100755 --- a/headers/os/kernel/syscalls.h +++ b/headers/os/kernel/syscalls.h @@ -23,23 +23,6 @@ extern "C" { int sys_null(); -/* fs api */ -int sys_mount(const char *path, const char *device, const char *fs_name, void *args); -int sys_unmount(const char *path); -int sys_sync(); -int sys_fsync(int fd); -int sys_create(const char *path, int omode, int perms); -int sys_open(const char *path, int omode); -int sys_close(int fd); -off_t sys_seek(int fd, off_t pos, int seek_type); -int sys_ioctl(int fd, ulong op, void *buf, size_t length); -int sys_unlink(const char *path); -int sys_rename(const char *oldpath, const char *newpath); -int sys_fstat(int, struct stat *); -char *sys_getcwd(char* buf, size_t size); -int sys_setcwd(const char* path); -int sys_dup(int fd); -int sys_dup2(int ofd, int nfd); int sys_getrlimit(int resource, struct rlimit * rlp); int sys_setrlimit(int resource, const struct rlimit * rlp); diff --git a/headers/posix/unistd.h b/headers/posix/unistd.h index 079e0fe36b..75d33a082c 100644 --- a/headers/posix/unistd.h +++ b/headers/posix/unistd.h @@ -69,9 +69,9 @@ extern "C" { /* file functions */ //extern int access(const char *path, int amode); -//extern int chdir(const char *path); -//extern int fchdir(int fd); -//extern char *getcwd(char *buffer, size_t size); +extern int chdir(const char *path); +extern int fchdir(int fd); +extern char *getcwd(char *buffer, size_t size); //extern int pipe(int fildes[2]); extern int dup(int fd); diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index a403bcd075..06a8082707 100755 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -166,9 +166,9 @@ int sys_create_symlink(const char *path, const char *toPath, int mode); int sys_unlink(const char *path); int sys_rename(const char *oldpath, const char *newpath); int sys_read_stat(const char *path, bool traverseLink, struct stat *stat); -int sys_write_stat(const char *path, bool traverseLink, struct stat *stat, int statMask); -char *sys_getcwd(char *buf, size_t size); -int sys_setcwd(const char* path); +int sys_write_stat(int fd, const char *path, bool traverseLink, struct stat *stat, int statMask); +int sys_getcwd(char *buffer, size_t size); +int sys_setcwd(int fd, const char *path); /* calls the syscall dispatcher should use for user file I/O */ int user_mount(const char *path, const char *device, const char *fs_name, void *args); @@ -191,9 +191,9 @@ int user_create_symlink(const char *path, const char *toPath, int mode); int user_unlink(const char *path); int user_rename(const char *oldpath, const char *newpath); int user_read_stat(const char *path, bool traverseLink, struct stat *stat); -int user_write_stat(const char *path, bool traverseLink, struct stat *stat, int statMask); -int user_getcwd(char *buf, size_t size); -int user_setcwd(const char* path); +int user_write_stat(int fd, const char *path, bool traverseLink, struct stat *stat, int statMask); +int user_getcwd(char *buffer, size_t size); +int user_setcwd(int fd, const char *path); /* fd kernel prototypes (implementation located in fd.c) */ extern ssize_t sys_read(int fd, off_t pos, void *buffer, size_t bufferSize); @@ -201,6 +201,7 @@ extern ssize_t sys_write(int fd, off_t pos, const void *buffer, size_t bufferSiz extern int sys_ioctl(int fd, ulong cmd, void *data, size_t length); extern ssize_t sys_read_dir(int fd, struct dirent *buffer, size_t bufferSize, uint32 maxCount); extern status_t sys_rewind_dir(int fd); +extern int sys_fstat(int fd, struct stat *); extern int sys_close(int fd); extern int sys_dup(int fd); extern int sys_dup2(int ofd, int nfd); @@ -211,7 +212,7 @@ extern ssize_t user_write(int fd, off_t pos, const void *buffer, size_t bufferSi extern int user_ioctl(int fd, ulong cmd, void *data, size_t length); extern ssize_t user_read_dir(int fd, struct dirent *buffer, size_t bufferSize, uint32 maxCount); extern status_t user_rewind_dir(int fd); -extern int user_fstat(int, struct stat *); +extern int user_fstat(int fd, struct stat *); extern int user_close(int fd); extern int user_dup(int fd); extern int user_dup2(int ofd, int nfd); diff --git a/src/add-ons/kernel/file_systems/bfs/ToDo b/src/add-ons/kernel/file_systems/bfs/ToDo index 9badbc44cc..aa2631bf79 100644 --- a/src/add-ons/kernel/file_systems/bfs/ToDo +++ b/src/add-ons/kernel/file_systems/bfs/ToDo @@ -1,4 +1,4 @@ -BFS - ToDo, June 5th, 2002 +BFS - ToDo, June 23th, 2002 ----- BlockAllocator @@ -21,6 +21,7 @@ Queries - There shouldn't be any cases where you can speed up a query with reordering the query expression - test it - Check permissions of the parent directories - Add protection against crashing applications which had a query open - at least the original BeOS kernel does not free the cookie (which throws some memory away *and* prevents unmounting the disk) + - the query set for "!=" and last_modified/size is not the same as for "="; last_modified/size don't contain directories Journal diff --git a/src/kernel/Jamfile b/src/kernel/Jamfile index 70c23bee5d..4bdea08b83 100644 --- a/src/kernel/Jamfile +++ b/src/kernel/Jamfile @@ -354,12 +354,14 @@ KernelStaticLibraryObjects libc.a : <$(SOURCE_GRIST)!libc!unistd>getopt.o <$(SOURCE_GRIST)!libc!unistd>lseek.o <$(SOURCE_GRIST)!libc!unistd>open.o - <$(SOURCE_GRIST)!libc!unistd>opendir.o + <$(SOURCE_GRIST)!libc!unistd>directory.o <$(SOURCE_GRIST)!libc!unistd>link.o <$(SOURCE_GRIST)!libc!unistd>read.o <$(SOURCE_GRIST)!libc!unistd>write.o <$(SOURCE_GRIST)!libc!unistd>sleep.o <$(SOURCE_GRIST)!libc!unistd>usleep.o + <$(SOURCE_GRIST)!libc!unistd>ioctl.o + <$(SOURCE_GRIST)!libc!unistd>conf.o ; KernelLd libc.so : @@ -469,12 +471,14 @@ KernelLd libc.so : <$(SOURCE_GRIST)!libc!unistd>getopt.o <$(SOURCE_GRIST)!libc!unistd>lseek.o <$(SOURCE_GRIST)!libc!unistd>open.o - <$(SOURCE_GRIST)!libc!unistd>opendir.o + <$(SOURCE_GRIST)!libc!unistd>directory.o <$(SOURCE_GRIST)!libc!unistd>link.o <$(SOURCE_GRIST)!libc!unistd>read.o <$(SOURCE_GRIST)!libc!unistd>write.o <$(SOURCE_GRIST)!libc!unistd>sleep.o <$(SOURCE_GRIST)!libc!unistd>usleep.o + <$(SOURCE_GRIST)!libc!unistd>ioctl.o + <$(SOURCE_GRIST)!libc!unistd>conf.o : $(SUBDIR)/ldscripts/$(OBOS_ARCH)/library.ld : diff --git a/src/kernel/apps/shell/commands.c b/src/kernel/apps/shell/commands.c index f649942a51..4367d36c86 100644 --- a/src/kernel/apps/shell/commands.c +++ b/src/kernel/apps/shell/commands.c @@ -4,9 +4,11 @@ */ #include +#include #include #include #include +#include #include "commands.h" #include "file_utils.h" @@ -135,31 +137,28 @@ int cmd_cd(int argc, char *argv[]) { int rc; - if(argc < 2) { + if (argc < 2) { printf("not enough arguments to cd\n"); return 0; } - rc = sys_setcwd(argv[1]); - if (rc < 0) { - printf("cd: sys_setcwd() returned error: %s!\n", strerror(rc)); - } + rc = chdir(argv[1]); + if (rc < 0) + printf("cd: sys_setcwd() returned error: %s!\n", strerror(errno)); return 0; } int cmd_pwd(int argc, char *argv[]) { - char buf[257]; - char *rc; + char buffer[SYS_MAX_PATH_LEN]; - rc = sys_getcwd(buf,256); - if (rc != NULL) { - printf("cd: sys_getcwd() returned error!\n"); + if (getcwd(buffer, sizeof(buffer)) == NULL) { + printf("cd: sys_getcwd() returned error: %s!\n", strerror(errno)); + return 0; } - buf[256] = 0; - printf("%s\n", buf); + printf("%s\n", buffer); return 0; } diff --git a/src/kernel/core/fd.c b/src/kernel/core/fd.c index 7257f941f9..7d9e3a59d4 100644 --- a/src/kernel/core/fd.c +++ b/src/kernel/core/fd.c @@ -375,7 +375,7 @@ int user_fstat(int fd, struct stat *stat) { struct file_descriptor *descriptor; - ssize_t retval; + status_t status; /* This is a user_function, so abort if we have a kernel address */ CHECK_USER_ADDR(stat) @@ -391,14 +391,14 @@ user_fstat(int fd, struct stat *stat) // lock the given stat buffer in memory struct stat kstat; - retval = descriptor->ops->fd_stat(descriptor, &kstat); - if (retval >= 0) - retval = user_memcpy(stat, &kstat, sizeof(*stat)); + status = descriptor->ops->fd_stat(descriptor, &kstat); + if (status >= 0) + status = user_memcpy(stat, &kstat, sizeof(*stat)); } else - retval = EOPNOTSUPP; + status = EOPNOTSUPP; put_fd(descriptor); - return retval; + return status; } @@ -572,6 +572,28 @@ sys_rewind_dir(int fd) } +int +sys_fstat(int fd, struct stat *stat) +{ + struct file_descriptor *descriptor; + status_t status; + + descriptor = get_fd(get_current_io_context(true), fd); + if (descriptor == NULL) + return EBADF; + + TRACE(("sys_fstat(descriptor = %p)\n",descriptor)); + + if (descriptor->ops->fd_stat) + status = descriptor->ops->fd_stat(descriptor, stat); + else + status = EOPNOTSUPP; + + put_fd(descriptor); + return status; +} + + int sys_close(int fd) { diff --git a/src/kernel/core/fs/vfs.c b/src/kernel/core/fs/vfs.c index 055f788277..da72bd2727 100755 --- a/src/kernel/core/fs/vfs.c +++ b/src/kernel/core/fs/vfs.c @@ -1,4 +1,11 @@ -/* Virtual File System */ +/* Virtual File System and +** File System Interface Layer +*/ + +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ /* ** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -439,7 +446,7 @@ err: } -static __inline void +static inline void put_vnode(struct vnode *vnode) { dec_vnode_ref_count(vnode, false); @@ -447,7 +454,7 @@ put_vnode(struct vnode *vnode) static struct file_descriptor * -get_fd_and_vnode(int fd, bool kernel, struct vnode **_vnode) +get_fd_and_vnode(int fd, struct vnode **_vnode, bool kernel) { struct file_descriptor *descriptor = get_fd(get_current_io_context(kernel), fd); if (descriptor == NULL) @@ -929,6 +936,27 @@ check_path(char *to) } +static status_t +fd_and_path_to_vnode(int fd, char *path, bool traverseLeafLink, struct vnode **_vnode, bool kernel) +{ + struct vnode *vnode; + + if (fd != -1) { + struct file_descriptor *descriptor = get_fd_and_vnode(fd, &vnode, kernel); + if (descriptor == NULL) + return EBADF; + + inc_vnode_ref_count(vnode); + put_fd(descriptor); + + *_vnode = vnode; + return B_OK; + } + + return path_to_vnode(path, traverseLeafLink, _vnode, kernel); +} + + // #pragma mark - // Functions the VFS exports for other parts of the kernel @@ -1443,7 +1471,7 @@ vfs_bootstrap_all_filesystems(void) if (err < 0) panic("error mounting rootfs!\n"); - sys_setcwd("/"); + sys_setcwd(-1, "/"); // bootstrap the bootfs bootstrap_bootfs(); @@ -1978,7 +2006,7 @@ common_sync(int fd, bool kernel) FUNCTION(("vfs_fsync: entry. fd %d kernel %d\n", fd, kernel)); - descriptor = get_fd_and_vnode(fd, kernel, &vnode); + descriptor = get_fd_and_vnode(fd, &vnode, kernel); if (descriptor == NULL) return ERR_INVALID_HANDLE; @@ -2121,14 +2149,14 @@ err: static int -common_write_stat(char *path, bool traverseLeafLink, const struct stat *stat, int statMask, bool kernel) +common_write_stat(int fd, char *path, bool traverseLeafLink, const struct stat *stat, int statMask, bool kernel) { struct vnode *vnode; int status; FUNCTION(("common_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel)); - status = path_to_vnode(path, traverseLeafLink, &vnode, kernel); + status = fd_and_path_to_vnode(fd, path, traverseLeafLink, &vnode, kernel); if (status < 0) return status; @@ -2446,7 +2474,7 @@ get_cwd(char *buffer, size_t size, bool kernel) static int -set_cwd(char *path, bool kernel) +set_cwd(int fd, char *path, bool kernel) { struct io_context *context; struct vnode *vnode = NULL; @@ -2457,7 +2485,7 @@ set_cwd(char *path, bool kernel) FUNCTION(("set_cwd: path = \'%s\'\n", path)); // Get vnode for passed path, and bail if it failed - rc = path_to_vnode(path, true, &vnode, kernel); + rc = fd_and_path_to_vnode(fd, path, true, &vnode, kernel); if (rc < 0) return rc; @@ -2745,50 +2773,55 @@ sys_read_stat(const char *path, bool traverseLeafLink, struct stat *stat) int -sys_write_stat(const char *path, bool traverseLeafLink, struct stat *stat, int statMask) +sys_write_stat(int fd, const char *_path, bool traverseLeafLink, struct stat *stat, int statMask) { - char buffer[SYS_MAX_PATH_LEN + 1]; + char path[SYS_MAX_PATH_LEN + 1]; - strncpy(buffer, path, SYS_MAX_PATH_LEN); - buffer[SYS_MAX_PATH_LEN] = 0; + if (fd == -1) { + strncpy(path, _path, SYS_MAX_PATH_LEN - 1); + path[SYS_MAX_PATH_LEN - 1] = '\0'; + } - return common_write_stat(buffer, traverseLeafLink, stat, statMask, true); -} - - -char * -sys_getcwd(char *buf, size_t size) -{ - char path[SYS_MAX_PATH_LEN]; - int rc; - - PRINT(("sys_getcwd: buf %p, %ld\n", buf, size)); - - // Call vfs to get current working directory - rc = get_cwd(path,SYS_MAX_PATH_LEN-1,true); - path[SYS_MAX_PATH_LEN-1] = 0; - - // Copy back the result - strncpy(buf,path,size); - - // Return either NULL or the buffer address to indicate failure or success - return (rc < 0) ? NULL : buf; + return common_write_stat(fd, path, traverseLeafLink, stat, statMask, true); } int -sys_setcwd(const char *_path) +sys_getcwd(char *buffer, size_t size) +{ + char path[SYS_MAX_PATH_LEN + 1]; + int status; + + PRINT(("sys_getcwd: buf %p, %ld\n", buffer, size)); + + // Call vfs to get current working directory + status = get_cwd(path, SYS_MAX_PATH_LEN - 1,true); + if (status < 0) + return status; + + path[SYS_MAX_PATH_LEN - 1] = '\0'; + strlcpy(buffer, path, size); + + return status; +} + + +int +sys_setcwd(int fd, const char *_path) { char path[SYS_MAX_PATH_LEN]; PRINT(("sys_setcwd: path = %s\n", _path)); - // Copy new path to kernel space - strncpy(path, _path, SYS_MAX_PATH_LEN-1); - path[SYS_MAX_PATH_LEN-1] = 0; + if (_path != NULL) { + // Copy new path to kernel space + strncpy(path, _path, SYS_MAX_PATH_LEN - 1); + path[SYS_MAX_PATH_LEN - 1] = '\0'; + } else + path[0] = '\0'; // Call vfs to set new working directory - return set_cwd(path,true); + return set_cwd(fd, path, true); } @@ -3174,26 +3207,28 @@ user_read_stat(const char *userPath, bool traverseLink, struct stat *userStat) int -user_write_stat(const char *userPath, bool traverseLeafLink, struct stat *userStat, int statMask) +user_write_stat(int fd, const char *userPath, bool traverseLeafLink, struct stat *userStat, int statMask) { - char path[SYS_MAX_PATH_LEN+1]; + char path[SYS_MAX_PATH_LEN + 1]; struct stat stat; int rc; - if (!CHECK_USER_ADDRESS(userPath) + if ((fd == -1 && !CHECK_USER_ADDRESS(userPath)) || !CHECK_USER_ADDRESS(userStat)) return B_BAD_ADDRESS; - rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); - if (rc < 0) - return rc; - path[SYS_MAX_PATH_LEN] = 0; + if (fd == -1) { + rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); + if (rc < 0) + return rc; + path[SYS_MAX_PATH_LEN - 1] = '\0'; + } rc = user_memcpy(&stat, userStat, sizeof(struct stat)); if (rc < 0) return rc; - return common_write_stat(path, traverseLeafLink, &stat, statMask, false); + return common_write_stat(fd, path, traverseLeafLink, &stat, statMask, false); } @@ -3223,25 +3258,27 @@ user_getcwd(char *buffer, size_t size) int -user_setcwd(const char *upath) +user_setcwd(int fd, const char *userPath) { char path[SYS_MAX_PATH_LEN]; int rc; - PRINT(("user_setcwd: path = %p\n", upath)); + PRINT(("user_setcwd: path = %p\n", userPath)); - // Check if userspace address is inside "shared" kernel space - if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; + if (userPath != NULL) { + if (!CHECK_USER_ADDRESS(userPath)) + return B_BAD_ADDRESS; - // Copy new path to kernel space - rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1); - if (rc < 0) - return rc; + // Copy new path to kernel space + rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); + if (rc < 0) + return rc; - path[SYS_MAX_PATH_LEN-1] = 0; + path[SYS_MAX_PATH_LEN - 1] = '\0'; + } else + path[0] = '\0'; // Call vfs to set new working directory - return set_cwd(path,false); + return set_cwd(fd, path, false); } diff --git a/src/kernel/core/syscalls.c b/src/kernel/core/syscalls.c index 7a2adb89cc..114216f5ee 100644 --- a/src/kernel/core/syscalls.c +++ b/src/kernel/core/syscalls.c @@ -130,7 +130,7 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re *call_ret = user_fstat((int)arg0, (struct stat*)arg1); break; case SYSCALL_WRITE_STAT: - *call_ret = user_write_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2, (int)arg3); + *call_ret = user_write_stat((int)arg0, (const char *)arg1, (bool)arg2, (struct stat *)arg3, (int)arg4); break; case SYSCALL_SYSTEM_TIME: *call_ret = system_time(); @@ -220,7 +220,7 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re *call_ret = user_getcwd((char*)arg0, (size_t)arg1); break; case SYSCALL_SETCWD: - *call_ret = user_setcwd((const char*)arg0); + *call_ret = user_setcwd((int)arg0, (const char *)arg1); break; case SYSCALL_PORT_CREATE: *call_ret = user_create_port((int32)arg0, (const char *)arg1);