diff --git a/headers/os/kernel/fs_interface.h b/headers/os/kernel/fs_interface.h index 7a78a1b4c1..fcacfbfc11 100644 --- a/headers/os/kernel/fs_interface.h +++ b/headers/os/kernel/fs_interface.h @@ -42,87 +42,89 @@ extern "C" { struct fs_calls { /* general operations */ - int (*fs_mount)(fs_id id, const char *device, void *args, fs_cookie *_fs, vnode_id *_rootVnodeID); - int (*fs_unmount)(fs_cookie fs); + status_t (*fs_mount)(fs_id id, const char *device, void *args, fs_cookie *_fs, vnode_id *_rootVnodeID); + status_t (*fs_unmount)(fs_cookie fs); - int (*fs_read_fs_info)(fs_cookie fs, struct fs_info *info); - int (*fs_write_fs_info)(fs_cookie fs, const struct fs_info *info, int mask); - int (*fs_sync)(fs_cookie fs); + status_t (*fs_read_fs_info)(fs_cookie fs, struct fs_info *info); + status_t (*fs_write_fs_info)(fs_cookie fs, const struct fs_info *info, int mask); + status_t (*fs_sync)(fs_cookie fs); /* vnode operations */ - int (*fs_lookup)(fs_cookie fs, fs_vnode dir, const char *name, vnode_id *_id, int *_type); - int (*fs_get_vnode_name)(fs_cookie fs, fs_vnode vnode, char *buffer, size_t bufferSize); + status_t (*fs_lookup)(fs_cookie fs, fs_vnode dir, const char *name, vnode_id *_id, int *_type); + status_t (*fs_get_vnode_name)(fs_cookie fs, fs_vnode vnode, char *buffer, size_t bufferSize); - int (*fs_get_vnode)(fs_cookie fs, vnode_id id, fs_vnode *_vnode, bool reenter); - int (*fs_put_vnode)(fs_cookie fs, fs_vnode vnode, bool reenter); - int (*fs_remove_vnode)(fs_cookie fs, fs_vnode vnode, bool reenter); + status_t (*fs_get_vnode)(fs_cookie fs, vnode_id id, fs_vnode *_vnode, bool reenter); + status_t (*fs_put_vnode)(fs_cookie fs, fs_vnode vnode, bool reenter); + status_t (*fs_remove_vnode)(fs_cookie fs, fs_vnode vnode, bool reenter); /* VM file access */ - int (*fs_can_page)(fs_cookie fs, fs_vnode v); + status_t (*fs_can_page)(fs_cookie fs, fs_vnode v); ssize_t (*fs_read_page)(fs_cookie fs, fs_vnode v, iovecs *vecs, off_t pos); ssize_t (*fs_write_page)(fs_cookie fs, fs_vnode v, iovecs *vecs, off_t pos); /* common operations */ - int (*fs_ioctl)(fs_cookie fs, fs_vnode v, file_cookie cookie, ulong op, void *buffer, size_t length); - int (*fs_fsync)(fs_cookie fs, fs_vnode v); + status_t (*fs_ioctl)(fs_cookie fs, fs_vnode v, file_cookie cookie, ulong op, void *buffer, size_t length); + status_t (*fs_fsync)(fs_cookie fs, fs_vnode v); - int (*fs_read_link)(fs_cookie fs, fs_vnode link, char *buffer, size_t bufferSize); - int (*fs_write_link)(fs_cookie fs, fs_vnode link, char *toPath); - int (*fs_symlink)(fs_cookie fs, fs_vnode dir, const char *name, const char *path, int mode); + status_t (*fs_read_link)(fs_cookie fs, fs_vnode link, char *buffer, size_t bufferSize); + status_t (*fs_write_link)(fs_cookie fs, fs_vnode link, char *toPath); + status_t (*fs_create_symlink)(fs_cookie fs, fs_vnode dir, const char *name, const char *path, int mode); - int (*fs_unlink)(fs_cookie fs, fs_vnode dir, const char *name); - int (*fs_rename)(fs_cookie fs, fs_vnode olddir, const char *oldname, fs_vnode newdir, const char *newname); + status_t (*fs_link)(fs_cookie fs, fs_vnode dir, const char *name, fs_vnode vnode); + status_t (*fs_unlink)(fs_cookie fs, fs_vnode dir, const char *name); + status_t (*fs_rename)(fs_cookie fs, fs_vnode olddir, const char *oldname, fs_vnode newdir, const char *newname); - int (*fs_access)(fs_cookie fs, fs_vnode vnode, int mode); - int (*fs_read_stat)(fs_cookie fs, fs_vnode vnode, struct stat *stat); - int (*fs_write_stat)(fs_cookie fs, fs_vnode vnode, const struct stat *stat, int statMask); + status_t (*fs_access)(fs_cookie fs, fs_vnode vnode, int mode); + status_t (*fs_read_stat)(fs_cookie fs, fs_vnode vnode, struct stat *stat); + status_t (*fs_write_stat)(fs_cookie fs, fs_vnode vnode, const struct stat *stat, int statMask); /* file operations */ - int (*fs_create)(fs_cookie fs, fs_vnode dir, const char *name, int omode, int perms, file_cookie *_cookie, vnode_id *_newVnodeID); - int (*fs_open)(fs_cookie fs, fs_vnode v, int oflags, file_cookie *_cookie); - int (*fs_close)(fs_cookie fs, fs_vnode v, file_cookie cookie); - int (*fs_free_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); + status_t (*fs_create)(fs_cookie fs, fs_vnode dir, const char *name, int omode, int perms, file_cookie *_cookie, vnode_id *_newVnodeID); + status_t (*fs_open)(fs_cookie fs, fs_vnode v, int oflags, file_cookie *_cookie); + status_t (*fs_close)(fs_cookie fs, fs_vnode v, file_cookie cookie); + status_t (*fs_free_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); ssize_t (*fs_read)(fs_cookie fs, fs_vnode v, file_cookie cookie, off_t pos, void *buffer, size_t *length); ssize_t (*fs_write)(fs_cookie fs, fs_vnode v, file_cookie cookie, off_t pos, const void *buffer, size_t *length); off_t (*fs_seek)(fs_cookie fs, fs_vnode v, file_cookie cookie, off_t pos, int seekType); /* directory operations */ - int (*fs_create_dir)(fs_cookie fs, fs_vnode parent, const char *name, int perms, vnode_id *_newVnodeID); - int (*fs_open_dir)(fs_cookie fs, fs_vnode v, file_cookie *_cookie); - int (*fs_close_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); - int (*fs_free_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); - int (*fs_read_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); - int (*fs_rewind_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); + status_t (*fs_create_dir)(fs_cookie fs, fs_vnode parent, const char *name, int perms, vnode_id *_newVnodeID); + status_t (*fs_remove_dir)(fs_cookie fs, fs_vnode dir, const char *name); + status_t (*fs_open_dir)(fs_cookie fs, fs_vnode v, file_cookie *_cookie); + status_t (*fs_close_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); + status_t (*fs_free_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); + status_t (*fs_read_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); + status_t (*fs_rewind_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); /* attribute directory operations */ -// int (*fs_open_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); -// int (*fs_close_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_free_attr_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_read_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); -// int (*fs_rewind_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_open_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); +// status_t (*fs_close_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_free_attr_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_read_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); +// status_t (*fs_rewind_attr_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); // // /* attribute operations */ -// int (*fs_open_attr)(fs_cookie fs, fs_vnode v, file_cookie *cookie, stream_type st, int oflags); -// int (*fs_close_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_free_attr_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_open_attr)(fs_cookie fs, fs_vnode v, file_cookie *cookie, stream_type st, int oflags); +// status_t (*fs_close_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_free_attr_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); // ssize_t (*fs_read_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie, void *buf, off_t pos, size_t *len); // ssize_t (*fs_write_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie, const void *buf, off_t pos, size_t *len); -// int (*fs_seek_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie, off_t pos, int st); -// int (*fs_rename_attr)(fs_cookie fs, fs_vnode file, const char *oldname, const char *newname); +// status_t (*fs_seek_attr)(fs_cookie fs, fs_vnode v, file_cookie cookie, off_t pos, int st); +// status_t (*fs_rename_attr)(fs_cookie fs, fs_vnode file, const char *oldname, const char *newname); // // /* index directory & index operations */ -// int (*fs_open_index_dir)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); -// int (*fs_close_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_free_index_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_read_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); -// int (*fs_rewind_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_open_index_dir)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); +// status_t (*fs_close_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_free_index_dir_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_read_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); +// status_t (*fs_rewind_index_dir)(fs_cookie fs, fs_vnode v, file_cookie cookie); // // /* query operations */ -// int (*fs_open_query)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); -// int (*fs_close_query)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_free_query_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); -// int (*fs_read_query)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); -// int (*fs_rewind_query)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_open_query)(fs_cookie fs, fs_vnode v, file_cookie *cookie, int oflags); +// status_t (*fs_close_query)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_free_query_cookie)(fs_cookie fs, fs_vnode v, file_cookie cookie); +// status_t (*fs_read_query)(fs_cookie fs, fs_vnode v, file_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num); +// status_t (*fs_rewind_query)(fs_cookie fs, fs_vnode v, file_cookie cookie); }; #ifdef __cplusplus diff --git a/headers/posix/unistd.h b/headers/posix/unistd.h index a131c72147..cf8220c1a1 100644 --- a/headers/posix/unistd.h +++ b/headers/posix/unistd.h @@ -77,9 +77,9 @@ extern char *getcwd(char *buffer, size_t size); extern int dup(int fd); extern int dup2(int fd1, int fd2); extern int close(int fd); -//extern int link(const char *name, const char *new_name); -//extern int unlink(const char *name); -//extern int rmdir(const char *path); +extern int link(const char *name, const char *new_name); +extern int unlink(const char *name); +extern int rmdir(const char *path); extern ssize_t readlink(const char *path, char *buffer, size_t bufferSize); extern int symlink(const char *from, const char *to); diff --git a/headers/private/kernel/ksyscalls.h b/headers/private/kernel/ksyscalls.h index 79df553195..68af99db4b 100755 --- a/headers/private/kernel/ksyscalls.h +++ b/headers/private/kernel/ksyscalls.h @@ -100,6 +100,8 @@ enum { SYSCALL_GET_NEXT_THREAD_INFO, SYSCALL_GET_TEAM_INFO, /* 90 */ SYSCALL_GET_NEXT_TEAM_INFO, + SYSCALL_CREATE_LINK, + SYSCALL_REMOVE_DIR, }; int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret); diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index de60ee255c..e50a75ba6d 100755 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -72,9 +72,11 @@ int sys_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omode int sys_create(const char *path, int omode, int perms); int sys_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms); int sys_create_dir(const char *path, int perms); +int sys_remove_dir(const char *path); int sys_read_link(const char *path, char *buffer, size_t bufferSize); int sys_write_link(const char *path, const char *toPath); int sys_create_symlink(const char *path, const char *toPath, int mode); +int sys_create_link(const char *path, const char *toPath); int sys_unlink(const char *path); int sys_rename(const char *oldpath, const char *newpath); int sys_access(const char *path, int mode); @@ -98,9 +100,11 @@ int user_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omod int user_create(const char *path, int omode, int perms); int user_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms); int user_create_dir(const char *path, int perms); +int user_remove_dir(const char *path); int user_read_link(const char *path, char *buffer, size_t bufferSize); int user_write_link(const char *path, const char *toPath); int user_create_symlink(const char *path, const char *toPath, int mode); +int user_create_link(const char *path, const char *toPath); int user_unlink(const char *path); int user_rename(const char *oldpath, const char *newpath); int user_access(const char *path, int mode); diff --git a/src/kernel/core/fs/bootfs.c b/src/kernel/core/fs/bootfs.c index 0244268b85..d97b8f541b 100755 --- a/src/kernel/core/fs/bootfs.c +++ b/src/kernel/core/fs/bootfs.c @@ -1031,6 +1031,7 @@ static struct fs_calls bootfs_calls = { NULL, // read_link NULL, // write_link NULL, // symlink + NULL, // link &bootfs_unlink, &bootfs_rename, @@ -1049,6 +1050,7 @@ static struct fs_calls bootfs_calls = { /* dir */ &bootfs_create_dir, + NULL, // remove_dir &bootfs_open_dir, &bootfs_close, // we are using the same operations for directories &bootfs_free_cookie, // and files here - that's intended, not by accident diff --git a/src/kernel/core/fs/devfs.c b/src/kernel/core/fs/devfs.c index 3495ea6634..bec8613351 100755 --- a/src/kernel/core/fs/devfs.c +++ b/src/kernel/core/fs/devfs.c @@ -998,7 +998,7 @@ devfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) status = vfs_remove_vnode(fs->id, vnode->id); -err: +err: mutex_unlock(&fs->lock); return status; @@ -1069,6 +1069,7 @@ static struct fs_calls devfs_calls = { NULL, // read_link NULL, // write_link NULL, // symlink + NULL, // link &devfs_unlink, &devfs_rename, @@ -1087,6 +1088,7 @@ static struct fs_calls devfs_calls = { /* directory */ &devfs_create_dir, + NULL, // remove_dir &devfs_open_dir, &devfs_close, // we are using the same operations for directories &devfs_free_cookie, // and files here - that's intended, not by accident diff --git a/src/kernel/core/fs/rootfs.c b/src/kernel/core/fs/rootfs.c index 3b20687c0c..712731ea44 100755 --- a/src/kernel/core/fs/rootfs.c +++ b/src/kernel/core/fs/rootfs.c @@ -225,6 +225,39 @@ rootfs_is_dir_empty(struct rootfs_vnode *dir) } +static int +rootfs_remove(struct rootfs *fs, struct rootfs_vnode *dir, const char *name, bool isDirectory) +{ + struct rootfs_vnode *vnode; + int status = B_OK; + + mutex_lock(&fs->lock); + + vnode = rootfs_find_in_dir(dir, name); + if (!vnode) + status = B_ENTRY_NOT_FOUND; + else if (isDirectory && vnode->stream.type != STREAM_TYPE_DIR) + status = B_NOT_A_DIRECTORY; + else if (!isDirectory && vnode->stream.type == STREAM_TYPE_DIR) + status = B_IS_A_DIRECTORY; + else if (isDirectory && !rootfs_is_dir_empty(vnode)) + status = B_DIRECTORY_NOT_EMPTY; + + if (status < B_OK) + goto err; + + rootfs_remove_from_dir(dir, vnode); + + // schedule this vnode to be removed when it's ref goes to zero + vfs_remove_vnode(fs->id, vnode->id); + +err: + mutex_unlock(&fs->lock); + + return status; +} + + // #pragma mark - @@ -565,6 +598,18 @@ err: } +static int +rootfs_remove_dir(fs_cookie _fs, fs_vnode _dir, const char *name) +{ + struct rootfs *fs = _fs; + struct rootfs_vnode *dir = _dir; + + TRACE(("rootfs_remove_dir: dir 0x%x (0x%x 0x%x), name '%s'\n", dir, dir->id, name)); + + return rootfs_remove(fs, dir, name, true); +} + + static int rootfs_open_dir(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie) { @@ -759,36 +804,10 @@ rootfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) { struct rootfs *fs = _fs; struct rootfs_vnode *dir = _dir; - struct rootfs_vnode *vnode; - int status; TRACE(("rootfs_unlink: dir 0x%x (0x%x 0x%x), name '%s'\n", dir, dir->id, name)); - mutex_lock(&fs->lock); - - vnode = rootfs_find_in_dir(dir, name); - if (!vnode) { - status = B_ENTRY_NOT_FOUND; - goto err; - } - - // if the node is a directory, only delete it if it's empty - if (vnode->stream.type == STREAM_TYPE_DIR && !rootfs_is_dir_empty(vnode)) { - status = B_DIRECTORY_NOT_EMPTY; - goto err; - } - - rootfs_remove_from_dir(dir, vnode); - - // schedule this vnode to be removed when it's ref goes to zero - vfs_remove_vnode(fs->id, vnode->id); - - status = 0; - -err: - mutex_unlock(&fs->lock); - - return status; + return rootfs_remove(fs, dir, name, false); } @@ -922,6 +941,7 @@ static struct fs_calls rootfs_calls = { &rootfs_read_link, NULL, // fs_write_link() &rootfs_symlink, + NULL, // fs_link() &rootfs_unlink, &rootfs_rename, @@ -940,6 +960,7 @@ static struct fs_calls rootfs_calls = { /* directory */ &rootfs_create_dir, + &rootfs_remove_dir, &rootfs_open_dir, &rootfs_close, // we are using the same operations for directories &rootfs_free_cookie, // and files here - that's intended, not by accident diff --git a/src/kernel/core/fs/vfs.c b/src/kernel/core/fs/vfs.c index c7da9167e9..6eef9687f5 100755 --- a/src/kernel/core/fs/vfs.c +++ b/src/kernel/core/fs/vfs.c @@ -730,6 +730,7 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel) /** Returns the vnode in the next to last segment of the path, and returns * the last portion in filename. + * The path buffer must be able to store at least one additional character. */ static int @@ -746,7 +747,6 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel // replace the filename portion of the path with a '.' strcpy(filename, ++p); - // ToDo: this could write behind the array limit if (p[0] != '\0'){ p[0] = '.'; p[1] = '\0'; @@ -899,6 +899,12 @@ out: } +/** Checks the length of every path component, and adds a '.' + * if the path ends in a slash. + * The given path buffer must be able to store at least one + * additional character. + */ + static status_t check_path(char *to) { @@ -1975,6 +1981,27 @@ dir_close(struct file_descriptor *descriptor) } +static status_t +dir_remove(char *path, bool kernel) +{ + char name[B_FILE_NAME_LENGTH]; + struct vnode *directory; + status_t status; + + status = path_to_dir_vnode(path, &directory, name, kernel); + if (status < B_OK) + return status; + + if (FS_CALL(directory, fs_remove_dir)) + status = FS_CALL(directory, fs_remove_dir)(directory->mount->cookie, directory->private_node, name); + else + status = EROFS; + + put_vnode(directory); + return status; +} + + static int common_read_stat(struct file_descriptor *descriptor, struct stat *stat) { @@ -2062,7 +2089,7 @@ common_write_link(char *path, char *toPath, bool kernel) } -static int +static status_t common_create_symlink(char *path, const char *toPath, int mode, bool kernel) { // path validity checks have to be in the calling function! @@ -2070,14 +2097,14 @@ common_create_symlink(char *path, const char *toPath, int mode, bool kernel) struct vnode *vnode; int status; - FUNCTION(("common_create_alias(path = %s, toPath = %s, mode = %d, kernel = %d)\n", path, toPath, mode, kernel)); + FUNCTION(("common_create_symlink(path = %s, toPath = %s, mode = %d, kernel = %d)\n", path, toPath, mode, kernel)); status = path_to_dir_vnode(path, &vnode, name, kernel); if (status < B_OK) return status; - if (FS_CALL(vnode,fs_symlink) != NULL) - status = FS_CALL(vnode,fs_symlink)(vnode->mount->cookie, vnode->private_node, name, toPath, mode); + if (FS_CALL(vnode,fs_create_symlink) != NULL) + status = FS_CALL(vnode,fs_create_symlink)(vnode->mount->cookie, vnode->private_node, name, toPath, mode); else status = EROFS; @@ -2087,7 +2114,44 @@ common_create_symlink(char *path, const char *toPath, int mode, bool kernel) } -static int +static status_t +common_create_link(char *path, char *toPath, bool kernel) +{ + // path validity checks have to be in the calling function! + char name[B_FILE_NAME_LENGTH]; + struct vnode *directory, *vnode; + int status; + + FUNCTION(("common_create_link(path = %s, toPath = %s, kernel = %d)\n", path, toPath, kernel)); + + status = path_to_dir_vnode(path, &directory, name, kernel); + if (status < B_OK) + return status; + + status = path_to_vnode(toPath, true, &vnode, kernel); + if (status < B_OK) + goto err; + + if (directory->mount != vnode->mount) { + status = B_CROSS_DEVICE_LINK; + goto err1; + } + + if (FS_CALL(vnode, fs_link) != NULL) + status = FS_CALL(vnode,fs_link)(directory->mount->cookie, directory->private_node, name, vnode->private_node); + else + status = EROFS; + +err1: + put_vnode(vnode); +err: + put_vnode(directory); + + return status; +} + + +static status_t common_unlink(char *path, bool kernel) { char filename[SYS_MAX_NAME_LEN]; @@ -2548,24 +2612,20 @@ err: int sys_mount(const char *path, const char *device, const char *fs_name, void *args) { - char buf[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(buf, path, SYS_MAX_PATH_LEN); - buf[SYS_MAX_PATH_LEN] = 0; - - return fs_mount(buf, device, fs_name, args, true); + return fs_mount(pathBuffer, device, fs_name, args, true); } int sys_unmount(const char *path) { - char buf[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(buf, path, SYS_MAX_PATH_LEN); - buf[SYS_MAX_PATH_LEN] = 0; - - return fs_unmount(buf, true); + return fs_unmount(pathBuffer, true); } @@ -2580,9 +2640,7 @@ int sys_open_entry_ref(dev_t device, ino_t inode, const char *name, int omode) { char nameCopy[B_FILE_NAME_LENGTH]; - - strncpy(nameCopy, name, sizeof(nameCopy) - 1); - nameCopy[sizeof(nameCopy) - 1] = '\0'; + strlcpy(nameCopy, name, sizeof(nameCopy) - 1); return file_open_entry_ref(device, inode, nameCopy, omode, true); } @@ -2591,12 +2649,10 @@ sys_open_entry_ref(dev_t device, ino_t inode, const char *name, int omode) int sys_open(const char *path, int omode) { - char pathCopy[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(pathCopy, path, SYS_MAX_PATH_LEN); - pathCopy[SYS_MAX_PATH_LEN] = 0; - - return file_open(pathCopy, omode, true); + return file_open(pathBuffer, omode, true); } @@ -2610,24 +2666,17 @@ sys_open_dir_node_ref(dev_t device, ino_t inode) int sys_open_dir_entry_ref(dev_t device, ino_t inode, const char *name) { - char nameCopy[B_FILE_NAME_LENGTH]; - - strncpy(nameCopy, name, sizeof(nameCopy) - 1); - nameCopy[sizeof(nameCopy) - 1] = '\0'; - - return dir_open_entry_ref(device, inode, nameCopy, true); + return dir_open_entry_ref(device, inode, name, true); } int sys_open_dir(const char *path) { - char buffer[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(buffer, path, SYS_MAX_PATH_LEN); - buffer[SYS_MAX_PATH_LEN] = 0; - - return dir_open(buffer, true); + return dir_open(pathBuffer, true); } @@ -2641,13 +2690,7 @@ sys_fsync(int fd) int sys_create_entry_ref(dev_t device, ino_t inode, const char *name, int omode, int perms) { - char nameCopy[B_FILE_NAME_LENGTH]; - int status; - - strncpy(nameCopy, name, sizeof(nameCopy) - 1); - nameCopy[sizeof(nameCopy) - 1] = '\0'; - - return file_create_entry_ref(device, inode, nameCopy, omode, perms, true); + return file_create_entry_ref(device, inode, name, omode, perms, true); } @@ -2655,9 +2698,7 @@ int sys_create(const char *path, int omode, int perms) { char buffer[SYS_MAX_PATH_LEN + 1]; - - strncpy(buffer, path, SYS_MAX_PATH_LEN); - buffer[SYS_MAX_PATH_LEN] = '\0'; + strlcpy(buffer, path, SYS_MAX_PATH_LEN - 1); return file_create(buffer, omode, perms, true); } @@ -2666,135 +2707,134 @@ sys_create(const char *path, int omode, int perms) int sys_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms) { - char nameCopy[B_FILE_NAME_LENGTH]; - - strncpy(nameCopy, name, sizeof(nameCopy) - 1); - nameCopy[sizeof(nameCopy) - 1] = '\0'; - - return dir_create_entry_ref(device, inode, nameCopy, perms, true); + return dir_create_entry_ref(device, inode, name, perms, true); } int sys_create_dir(const char *path, int perms) { - char buffer[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(buffer, path, SYS_MAX_PATH_LEN); - buffer[SYS_MAX_PATH_LEN] = 0; + return dir_create(pathBuffer, perms, true); +} - return dir_create(buffer, perms, true); + +int +sys_remove_dir(const char *path) +{ + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); + + return dir_remove(pathBuffer, true); } int sys_read_link(const char *path, char *buffer, size_t bufferSize) { - char pathCopy[SYS_MAX_PATH_LEN + 1]; - int status; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(pathCopy, path, SYS_MAX_PATH_LEN); - pathCopy[SYS_MAX_PATH_LEN] = '\0'; - - return common_read_link(pathCopy, buffer, bufferSize, true); + return common_read_link(pathBuffer, buffer, bufferSize, true); } int sys_write_link(const char *path, const char *toPath) { - char pathCopy[SYS_MAX_PATH_LEN + 1]; - char toPathCopy[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + char toPathBuffer[SYS_MAX_PATH_LEN + 1]; int status; - strncpy(pathCopy, path, SYS_MAX_PATH_LEN); - pathCopy[SYS_MAX_PATH_LEN] = '\0'; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); + strlcpy(toPathBuffer, toPath, SYS_MAX_PATH_LEN - 1); - strncpy(toPathCopy, toPath, SYS_MAX_PATH_LEN); - toPathCopy[SYS_MAX_PATH_LEN] = '\0'; - - status = check_path(toPathCopy); + status = check_path(toPathBuffer); if (status < B_OK) return status; - return common_write_link(pathCopy, toPathCopy, true); + return common_write_link(pathBuffer, toPathBuffer, true); } int -sys_create_symlink(const char *userPath, const char *userToPath, int mode) +sys_create_symlink(const char *path, const char *toPath, int mode) { - char path[SYS_MAX_PATH_LEN + 1]; - char toPath[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + char toPathBuffer[SYS_MAX_PATH_LEN + 1]; int status; - - strncpy(path, userPath, SYS_MAX_PATH_LEN); - path[SYS_MAX_PATH_LEN] = '\0'; - strncpy(toPath, userToPath, SYS_MAX_PATH_LEN); - toPath[SYS_MAX_PATH_LEN] = '\0'; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); + strlcpy(toPathBuffer, toPath, SYS_MAX_PATH_LEN - 1); - status = check_path(toPath); + status = check_path(toPathBuffer); if (status < B_OK) return status; - return common_create_symlink(path, toPath, mode, true); + return common_create_symlink(pathBuffer, toPathBuffer, mode, true); +} + + +int +sys_create_link(const char *path, const char *toPath) +{ + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + char toPathBuffer[SYS_MAX_PATH_LEN + 1]; + + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); + strlcpy(toPathBuffer, toPath, SYS_MAX_PATH_LEN - 1); + + return common_create_link(pathBuffer, toPathBuffer, true); } int sys_unlink(const char *path) { - char buf[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strncpy(buf, path, SYS_MAX_PATH_LEN); - buf[SYS_MAX_PATH_LEN] = 0; - - return common_unlink(buf, true); + return common_unlink(pathBuffer, true); } int -sys_rename(const char *oldpath, const char *newpath) +sys_rename(const char *oldPath, const char *newPath) { - char buf1[SYS_MAX_PATH_LEN + 1]; - char buf2[SYS_MAX_PATH_LEN + 1]; + char oldPathBuffer[SYS_MAX_PATH_LEN + 1]; + char newPathBuffer[SYS_MAX_PATH_LEN + 1]; - strncpy(buf1, oldpath, SYS_MAX_PATH_LEN); - buf1[SYS_MAX_PATH_LEN] = 0; + strlcpy(oldPathBuffer, oldPath, SYS_MAX_PATH_LEN - 1); + strlcpy(newPathBuffer, newPath, SYS_MAX_PATH_LEN - 1); - strncpy(buf2, newpath, SYS_MAX_PATH_LEN); - buf2[SYS_MAX_PATH_LEN] = 0; - - return common_rename(buf1, buf2, true); + return common_rename(oldPathBuffer, newPathBuffer, true); } int sys_access(const char *path, int mode) { - char pathCopy[SYS_MAX_PATH_LEN + 1]; - int status; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - strlcpy(pathCopy, path, SYS_MAX_PATH_LEN - 1); - - return common_access(pathCopy, mode, true); + return common_access(pathBuffer, mode, true); } int sys_read_stat(const char *path, bool traverseLeafLink, struct stat *stat) { - char buffer[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; struct vnode *vnode; int status; - strncpy(buffer, path, SYS_MAX_PATH_LEN); - buffer[SYS_MAX_PATH_LEN] = 0; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); FUNCTION(("sys_read_stat: path '%s', stat %p,\n", path, stat)); - status = path_to_vnode(buffer, traverseLeafLink, &vnode, true); + status = path_to_vnode(pathBuffer, traverseLeafLink, &vnode, true); if (status < 0) return status; @@ -2806,29 +2846,27 @@ sys_read_stat(const char *path, bool traverseLeafLink, struct stat *stat) int -sys_write_stat(int fd, 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 path[SYS_MAX_PATH_LEN + 1]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; - if (fd == -1) { - strncpy(path, _path, SYS_MAX_PATH_LEN - 1); - path[SYS_MAX_PATH_LEN - 1] = '\0'; - } + if (fd == -1) + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - return common_write_stat(fd, path, traverseLeafLink, stat, statMask, true); + return common_write_stat(fd, pathBuffer, traverseLeafLink, stat, statMask, true); } int sys_getcwd(char *buffer, size_t size) { - char path[SYS_MAX_PATH_LEN + 1]; + char path[SYS_MAX_PATH_LEN]; 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); + status = get_cwd(path, SYS_MAX_PATH_LEN - 1, true); if (status < 0) return status; @@ -2840,21 +2878,12 @@ sys_getcwd(char *buffer, size_t size) int -sys_setcwd(int fd, const char *_path) +sys_setcwd(int fd, const char *path) { - char path[SYS_MAX_PATH_LEN]; + char pathBuffer[SYS_MAX_PATH_LEN + 1]; + strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); - PRINT(("sys_setcwd: path = %s\n", _path)); - - 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(fd, path, true); + return set_cwd(fd, pathBuffer, true); } @@ -2875,23 +2904,23 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a || !CHECK_USER_ADDRESS(udevice)) return B_BAD_ADDRESS; - rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN); + rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1); if (rc < 0) return rc; - path[SYS_MAX_PATH_LEN] = 0; + path[SYS_MAX_PATH_LEN - 1] = '\0'; - rc = user_strncpy(fs_name, ufs_name, SYS_MAX_OS_NAME_LEN); + rc = user_strncpy(fs_name, ufs_name, SYS_MAX_OS_NAME_LEN - 1); if (rc < 0) return rc; - fs_name[SYS_MAX_OS_NAME_LEN] = 0; + fs_name[SYS_MAX_OS_NAME_LEN - 1] = '\0'; if (udevice) { - rc = user_strncpy(device, udevice, SYS_MAX_PATH_LEN); + rc = user_strncpy(device, udevice, SYS_MAX_PATH_LEN - 1); if (rc < 0) return rc; - device[SYS_MAX_PATH_LEN] = 0; + device[SYS_MAX_PATH_LEN - 1] = '\0'; } else - device[0] = 0; + device[0] = '\0'; return fs_mount(path, device, fs_name, args, false); } @@ -2901,12 +2930,12 @@ int user_unmount(const char *upath) { char path[SYS_MAX_PATH_LEN + 1]; - int rc; + int status; - rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN); - if (rc < 0) - return rc; - path[SYS_MAX_PATH_LEN] = 0; + status = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + path[SYS_MAX_PATH_LEN - 1] = '\0'; return fs_unmount(path, false); } @@ -2920,15 +2949,15 @@ user_sync(void) int -user_open_entry_ref(dev_t device, ino_t inode, const char *uname, int omode) +user_open_entry_ref(dev_t device, ino_t inode, const char *userName, int omode) { char name[B_FILE_NAME_LENGTH]; int status; - if (!CHECK_USER_ADDRESS(uname)) + if (!CHECK_USER_ADDRESS(userName)) return ERR_VM_BAD_USER_MEMORY; - status = user_strncpy(name, uname, sizeof(name) - 1); + status = user_strncpy(name, userName, sizeof(name) - 1); if (status < B_OK) return status; name[sizeof(name) - 1] = '\0'; @@ -2938,18 +2967,18 @@ user_open_entry_ref(dev_t device, ino_t inode, const char *uname, int omode) int -user_open(const char *upath, int omode) +user_open(const char *userPath, int omode) { char path[SYS_MAX_PATH_LEN + 1]; - int rc; + int status; - if (!CHECK_USER_ADDRESS(upath)) + if (!CHECK_USER_ADDRESS(userPath)) return ERR_VM_BAD_USER_MEMORY; - rc = user_strncpy(path, upath, sizeof(path)); - if (rc < 0) - return rc; - path[sizeof(path)] = 0; + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + path[SYS_MAX_PATH_LEN - 1] = '\0'; return file_open(path, omode, false); } @@ -2981,18 +3010,18 @@ user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname) int -user_open_dir(const char *upath) +user_open_dir(const char *userPath) { char path[SYS_MAX_PATH_LEN + 1]; int status; - if (!CHECK_USER_ADDRESS(upath)) + if (!CHECK_USER_ADDRESS(userPath)) return ERR_VM_BAD_USER_MEMORY; - status = user_strncpy(path, upath, sizeof(path)); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[sizeof(path)] = 0; + path[SYS_MAX_PATH_LEN - 1] = 0; return dir_open(path, false); } @@ -3024,18 +3053,18 @@ user_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omode, i int -user_create(const char *upath, int omode, int perms) +user_create(const char *userPath, int omode, int perms) { char path[SYS_MAX_PATH_LEN + 1]; int status; - if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; + if (!CHECK_USER_ADDRESS(userPath)) + return B_BAD_ADDRESS; - status = user_strncpy(path, upath, SYS_MAX_PATH_LEN); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[SYS_MAX_PATH_LEN] = '\0'; + path[SYS_MAX_PATH_LEN - 1] = '\0'; return file_create(path, omode, perms, false); } @@ -3048,7 +3077,7 @@ user_create_dir_entry_ref(dev_t device, ino_t inode, const char *uname, int perm int status; if (!CHECK_USER_ADDRESS(uname)) - return ERR_VM_BAD_USER_MEMORY; + return B_BAD_ADDRESS; status = user_strncpy(name, uname, sizeof(name) - 1); if (status < 0) @@ -3066,17 +3095,35 @@ user_create_dir(const char *userPath, int perms) int status; if (!CHECK_USER_ADDRESS(userPath)) - return ERR_VM_BAD_USER_MEMORY; + return B_BAD_ADDRESS; - status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[SYS_MAX_PATH_LEN] = '\0'; + path[SYS_MAX_PATH_LEN - 1] = '\0'; return dir_create(path, perms, false); } +int +user_remove_dir(const char *userPath) +{ + char path[SYS_MAX_PATH_LEN + 1]; + int status; + + if (!CHECK_USER_ADDRESS(userPath)) + return B_BAD_ADDRESS; + + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + path[SYS_MAX_PATH_LEN - 1] = '\0'; + + return dir_remove(path, false); +} + + int user_read_link(const char *userPath, char *userBuffer, size_t bufferSize) { @@ -3088,16 +3135,19 @@ user_read_link(const char *userPath, char *userBuffer, size_t bufferSize) || !CHECK_USER_ADDRESS(userBuffer)) return B_BAD_ADDRESS; - status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[SYS_MAX_PATH_LEN] = '\0'; + path[SYS_MAX_PATH_LEN - 1] = '\0'; + + if (bufferSize > SYS_MAX_PATH_LEN) + bufferSize = SYS_MAX_PATH_LEN; status = common_read_link(path, buffer, bufferSize, false); if (status < B_OK) return status; - return user_strncpy(userBuffer, buffer, SYS_MAX_PATH_LEN); + return user_strncpy(userBuffer, buffer, bufferSize); } @@ -3112,15 +3162,15 @@ user_write_link(const char *userPath, const char *userToPath) || !CHECK_USER_ADDRESS(userToPath)) return B_BAD_ADDRESS; - status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[SYS_MAX_PATH_LEN] = '\0'; + path[SYS_MAX_PATH_LEN - 1] = '\0'; - status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN); + status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - toPath[SYS_MAX_PATH_LEN] = '\0'; + toPath[SYS_MAX_PATH_LEN - 1] = '\0'; status = check_path(toPath); if (status < B_OK) @@ -3141,15 +3191,15 @@ user_create_symlink(const char *userPath, const char *userToPath, int mode) || !CHECK_USER_ADDRESS(userToPath)) return B_BAD_ADDRESS; - status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - path[SYS_MAX_PATH_LEN] = '\0'; + path[SYS_MAX_PATH_LEN - 1] = '\0'; - status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN); + status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN - 1); if (status < 0) return status; - toPath[SYS_MAX_PATH_LEN] = '\0'; + toPath[SYS_MAX_PATH_LEN - 1] = '\0'; status = check_path(toPath); if (status < B_OK) @@ -3159,6 +3209,35 @@ user_create_symlink(const char *userPath, const char *userToPath, int mode) } +int +user_create_link(const char *userPath, const char *userToPath) +{ + char path[SYS_MAX_PATH_LEN + 1]; + char toPath[SYS_MAX_PATH_LEN + 1]; + int status; + + if (!CHECK_USER_ADDRESS(userPath) + || !CHECK_USER_ADDRESS(userToPath)) + return B_BAD_ADDRESS; + + status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + path[SYS_MAX_PATH_LEN - 1] = '\0'; + + status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + toPath[SYS_MAX_PATH_LEN - 1] = '\0'; + + status = check_path(toPath); + if (status < B_OK) + return status; + + return common_create_link(path, toPath, false); +} + + int user_unlink(const char *userPath) { @@ -3178,29 +3257,26 @@ user_unlink(const char *userPath) int -user_rename(const char *uoldpath, const char *unewpath) +user_rename(const char *userOldPath, const char *userNewPath) { - char oldpath[SYS_MAX_PATH_LEN + 1]; - char newpath[SYS_MAX_PATH_LEN + 1]; - int rc; + char oldPath[SYS_MAX_PATH_LEN + 1]; + char newPath[SYS_MAX_PATH_LEN + 1]; + int status; - if ((addr)uoldpath >= KERNEL_BASE && (addr)uoldpath <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; + if (!CHECK_USER_ADDRESS(userOldPath) || !CHECK_USER_ADDRESS(userNewPath)) + return B_BAD_ADDRESS; - if ((addr)unewpath >= KERNEL_BASE && (addr)unewpath <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; + status = user_strncpy(oldPath, userOldPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + oldPath[SYS_MAX_PATH_LEN - 1] = '\0'; - rc = user_strncpy(oldpath, uoldpath, SYS_MAX_PATH_LEN); - if (rc < 0) - return rc; - oldpath[SYS_MAX_PATH_LEN] = 0; + status = user_strncpy(newPath, userNewPath, SYS_MAX_PATH_LEN - 1); + if (status < 0) + return status; + newPath[SYS_MAX_PATH_LEN - 1] = '\0'; - rc = user_strncpy(newpath, unewpath, SYS_MAX_PATH_LEN); - if (rc < 0) - return rc; - newpath[SYS_MAX_PATH_LEN] = 0; - - return common_rename(oldpath, newpath, false); + return common_rename(oldPath, newPath, false); } @@ -3234,10 +3310,10 @@ user_read_stat(const char *userPath, bool traverseLink, struct stat *userStat) || !CHECK_USER_ADDRESS(userStat)) return B_BAD_ADDRESS; - rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN); + rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN - 1); if (rc < 0) return rc; - path[SYS_MAX_PATH_LEN] = 0; + path[SYS_MAX_PATH_LEN - 1] = '\0'; FUNCTION(("user_read_stat(path = %s, traverseLeafLink = %d)\n", path, traverseLink)); @@ -3284,24 +3360,26 @@ user_write_stat(int fd, const char *userPath, bool traverseLeafLink, struct stat int -user_getcwd(char *buffer, size_t size) +user_getcwd(char *userBuffer, size_t size) { - char path[SYS_MAX_PATH_LEN]; + char buffer[SYS_MAX_PATH_LEN]; int status; - PRINT(("user_getcwd: buf %p, %ld\n", buffer, size)); + PRINT(("user_getcwd: buf %p, %ld\n", userBuffer, size)); - // Check if userspace address is inside "shared" kernel space - if ((addr)buffer >= KERNEL_BASE && (addr)buffer <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; + if (!CHECK_USER_ADDRESS(userBuffer)) + return B_BAD_ADDRESS; + + if (size > SYS_MAX_PATH_LEN) + size = SYS_MAX_PATH_LEN; // Call vfs to get current working directory - status = get_cwd(path, sizeof(path), false); + status = get_cwd(buffer, size, false); if (status < 0) return status; // Copy back the result - if (user_strncpy(buffer, path, size) < 0) + if (user_strncpy(userBuffer, buffer, size) < 0) return ERR_VM_BAD_USER_MEMORY; return status; @@ -3316,15 +3394,13 @@ user_setcwd(int fd, const char *userPath) PRINT(("user_setcwd: path = %p\n", userPath)); - if (userPath != NULL) { + if (fd == -1) { if (!CHECK_USER_ADDRESS(userPath)) return B_BAD_ADDRESS; - // 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'; } else path[0] = '\0'; diff --git a/src/kernel/core/syscalls.c b/src/kernel/core/syscalls.c index a6451f7e09..bb66d7e8ed 100644 --- a/src/kernel/core/syscalls.c +++ b/src/kernel/core/syscalls.c @@ -114,9 +114,15 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re case SYSCALL_CREATE_SYMLINK: *call_ret = user_create_symlink((const char *)arg0, (const char *)arg1, (int)arg2); break; + case SYSCALL_CREATE_LINK: + *call_ret = user_create_link((const char *)arg0, (const char *)arg1); + break; case SYSCALL_READ_LINK: *call_ret = user_read_link((const char *)arg0, (char *)arg1, (size_t)arg2); break; + case SYSCALL_REMOVE_DIR: + *call_ret = user_remove_dir((const char *)arg0); + break; case SYSCALL_UNLINK: *call_ret = user_unlink((const char *)arg0); break;