diff --git a/headers/private/kernel/syscalls.h b/headers/private/kernel/syscalls.h index 193b1382d6..62afb6d17c 100644 --- a/headers/private/kernel/syscalls.h +++ b/headers/private/kernel/syscalls.h @@ -145,7 +145,7 @@ extern status_t _kern_fsync(int fd); extern off_t _kern_seek(int fd, off_t pos, int seekType); extern status_t _kern_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms); extern status_t _kern_create_dir(int fd, const char *path, int perms); -extern status_t _kern_remove_dir(const char *path); +extern status_t _kern_remove_dir(int fd, const char *path); extern status_t _kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize); extern status_t _kern_write_link(const char *path, const char *toPath); diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index e41536d9ed..9fe3d96f88 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -136,7 +136,7 @@ status_t _user_write_stat(int fd, const char *path, bool traverseLink, off_t _user_seek(int fd, off_t pos, int seekType); status_t _user_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms); status_t _user_create_dir(int fd, const char *path, int perms); -status_t _user_remove_dir(const char *path); +status_t _user_remove_dir(int fd, const char *path); status_t _user_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize); status_t _user_write_link(const char *path, const char *toPath); status_t _user_create_symlink(int fd, const char *path, const char *toPath, diff --git a/src/kits/storage/Entry.cpp b/src/kits/storage/Entry.cpp index 77e51e8430..eecf6200b9 100644 --- a/src/kits/storage/Entry.cpp +++ b/src/kits/storage/Entry.cpp @@ -707,6 +707,10 @@ BEntry::Remove() { if (fCStatus != B_OK) return B_NO_INIT; + + if (IsDirectory()) + return _kern_remove_dir(fDirFd, fName); + return _kern_unlink(fDirFd, fName); } diff --git a/src/kits/storage/LibBeAdapter.cpp b/src/kits/storage/LibBeAdapter.cpp index 1917686298..caf38c9f0f 100644 --- a/src/kits/storage/LibBeAdapter.cpp +++ b/src/kits/storage/LibBeAdapter.cpp @@ -541,6 +541,24 @@ _kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize) return B_OK; } + +// _kern_remove_dir +extern "C" +status_t +_kern_remove_dir(int fd, const char *relPath) +{ + BPath path; + status_t error = get_path(fd, relPath, path); + if (error != B_OK) + return error; + + if (rmdir(path.Path()) < 0) { + return errno; + + return B_OK; +} + + // _kern_unlink extern "C" status_t @@ -550,17 +568,14 @@ _kern_unlink(int fd, const char *relPath) status_t error = get_path(fd, relPath, path); if (error != B_OK) return error; - if (unlink(path.Path()) < 0) { - error = errno; - if (error == B_IS_A_DIRECTORY) { - if (rmdir(path.Path()) < 0) - return errno; - } else - return error; - } + + if (unlink(path.Path()) < 0) + return errno; + return B_OK; } + // _kern_rename extern "C" status_t diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index eb1532ca5c..0cc2910d04 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -3739,19 +3739,20 @@ dir_rewind(struct file_descriptor *descriptor) static status_t -dir_remove(char *path, bool kernel) +dir_remove(int fd, 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) + + status = fd_and_path_to_dir_vnode(fd, path, &directory, name, kernel); + if (status < 0) return status; - if (FS_CALL(directory, remove_dir)) - status = FS_CALL(directory, remove_dir)(directory->mount->cookie, directory->private_node, name); - else + if (FS_CALL(directory, remove_dir)) { + status = FS_CALL(directory, remove_dir)(directory->mount->cookie, + directory->private_node, name); + } else status = EROFS; put_vnode(directory); @@ -5780,13 +5781,17 @@ _kern_create_dir(int fd, const char *path, int perms) status_t -_kern_remove_dir(const char *path) +_kern_remove_dir(int fd, const char *path) { - KPath pathBuffer(path, false, B_PATH_NAME_LENGTH + 1); - if (pathBuffer.InitCheck() != B_OK) - return B_NO_MEMORY; + if (path) { + KPath pathBuffer(path, false, B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - return dir_remove(pathBuffer.LockBuffer(), true); + return dir_remove(fd, pathBuffer.LockBuffer(), true); + } + + return dir_remove(fd, NULL, true); } @@ -6634,19 +6639,15 @@ _user_create_dir(int fd, const char *userPath, int perms) status_t -_user_remove_dir(const char *userPath) +_user_remove_dir(int fd, const char *userPath) { char path[B_PATH_NAME_LENGTH + 1]; - status_t status; - if (!IS_USER_ADDRESS(userPath)) + if ((userPath != NULL && !IS_USER_ADDRESS(userPath)) + || (userPath != NULL && user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK)) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - return dir_remove(path, false); + return dir_remove(fd, userPath ? path : NULL, false); } diff --git a/src/system/libroot/posix/unistd/directory.c b/src/system/libroot/posix/unistd/directory.c index 482ec1a1b1..790738cc4e 100644 --- a/src/system/libroot/posix/unistd/directory.c +++ b/src/system/libroot/posix/unistd/directory.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -68,7 +68,7 @@ getcwd(char *buffer, size_t size) int rmdir(const char *path) { - int status = _kern_remove_dir(path); + int status = _kern_remove_dir(-1, path); RETURN_AND_SET_ERRNO(status); }