mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-28 13:43:45 +03:00
Kernel+Userland: Implement fchmod() syscall and use it to improve /bin/cp.
/bin/cp will now copy the permission bits from source to destination. :^)
This commit is contained in:
parent
b5e5f26a82
commit
1b16a29044
Notes:
sideshowbarker
2024-07-19 15:34:50 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/1b16a290449
@ -138,6 +138,13 @@ int FileDescriptor::fstat(stat* buffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
KResult FileDescriptor::fchmod(mode_t mode)
|
||||
{
|
||||
if (!m_inode)
|
||||
return KResult(-EBADF);
|
||||
return VFS::the().chmod(*m_inode, mode);
|
||||
}
|
||||
|
||||
off_t FileDescriptor::seek(off_t offset, int whence)
|
||||
{
|
||||
ASSERT(!is_fifo());
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
ssize_t write(Process&, const byte* data, ssize_t);
|
||||
int fstat(stat*);
|
||||
|
||||
KResult fchmod(mode_t);
|
||||
|
||||
bool can_read(Process&);
|
||||
bool can_write(Process&);
|
||||
|
||||
|
@ -2177,6 +2177,14 @@ int Process::sys$chmod(const char* pathname, mode_t mode)
|
||||
return VFS::the().chmod(String(pathname), mode, cwd_inode());
|
||||
}
|
||||
|
||||
int Process::sys$fchmod(int fd, mode_t mode)
|
||||
{
|
||||
auto* descriptor = file_descriptor(fd);
|
||||
if (!descriptor)
|
||||
return -EBADF;
|
||||
return descriptor->fchmod(mode);
|
||||
}
|
||||
|
||||
int Process::sys$chown(const char* pathname, uid_t uid, gid_t gid)
|
||||
{
|
||||
if (!validate_read_str(pathname))
|
||||
|
@ -219,6 +219,7 @@ public:
|
||||
int sys$rmdir(const char* pathname);
|
||||
int sys$read_tsc(dword* lsw, dword* msw);
|
||||
int sys$chmod(const char* pathname, mode_t);
|
||||
int sys$fchmod(int fd, mode_t);
|
||||
int sys$chown(const char* pathname, uid_t, gid_t);
|
||||
int sys$socket(int domain, int type, int protocol);
|
||||
int sys$bind(int sockfd, const sockaddr* addr, socklen_t);
|
||||
|
@ -199,6 +199,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
||||
return current->sys$rmdir((const char*)arg1);
|
||||
case Syscall::SC_chmod:
|
||||
return current->sys$chmod((const char*)arg1, (mode_t)arg2);
|
||||
case Syscall::SC_fchmod:
|
||||
return current->sys$fchmod((int)arg1, (mode_t)arg2);
|
||||
case Syscall::SC_socket:
|
||||
return current->sys$socket((int)arg1, (int)arg2, (int)arg3);
|
||||
case Syscall::SC_bind:
|
||||
|
@ -83,6 +83,7 @@
|
||||
__ENUMERATE_SYSCALL(release_shared_buffer) \
|
||||
__ENUMERATE_SYSCALL(link) \
|
||||
__ENUMERATE_SYSCALL(chown) \
|
||||
__ENUMERATE_SYSCALL(fchmod) \
|
||||
|
||||
|
||||
namespace Syscall {
|
||||
|
@ -290,24 +290,26 @@ KResult VFS::access(const String& path, int mode, Inode& base)
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
KResult VFS::chmod(Inode& inode, mode_t mode)
|
||||
{
|
||||
if (inode.fs().is_readonly())
|
||||
return KResult(-EROFS);
|
||||
|
||||
if (current->euid() != inode.metadata().uid && !current->is_superuser())
|
||||
return KResult(-EPERM);
|
||||
|
||||
// Only change the permission bits.
|
||||
mode = (inode.mode() & ~04777u) | (mode & 04777u);
|
||||
return inode.chmod(mode);
|
||||
}
|
||||
|
||||
KResult VFS::chmod(const String& path, mode_t mode, Inode& base)
|
||||
{
|
||||
auto inode_or_error = resolve_path_to_inode(path, base);
|
||||
if (inode_or_error.is_error())
|
||||
return inode_or_error.error();
|
||||
auto inode = inode_or_error.value();
|
||||
|
||||
if (inode->fs().is_readonly())
|
||||
return KResult(-EROFS);
|
||||
|
||||
if (current->euid() != inode->metadata().uid && !current->is_superuser())
|
||||
return KResult(-EPERM);
|
||||
|
||||
// Only change the permission bits.
|
||||
mode = (inode->mode() & ~04777) | (mode & 04777);
|
||||
|
||||
kprintf("VFS::chmod(): %u:%u mode %o\n", inode->fsid(), inode->index(), mode);
|
||||
return inode->chmod(mode);
|
||||
return chmod(*inode, mode);
|
||||
}
|
||||
|
||||
KResult VFS::chown(const String& path, uid_t a_uid, gid_t a_gid, Inode& base)
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
KResult unlink(const String& path, Inode& base);
|
||||
KResult rmdir(const String& path, Inode& base);
|
||||
KResult chmod(const String& path, mode_t, Inode& base);
|
||||
KResult chmod(Inode&, mode_t);
|
||||
KResult chown(const String& path, uid_t, gid_t, Inode& base);
|
||||
KResult access(const String& path, int mode, Inode& base);
|
||||
bool stat(const String& path, int& error, int options, Inode& base, struct stat&);
|
||||
|
@ -25,8 +25,8 @@ int chmod(const char* pathname, mode_t mode)
|
||||
|
||||
int fchmod(int fd, mode_t mode)
|
||||
{
|
||||
dbgprintf("FIXME(LibC): fchmod(%d, %o)\n", fd, mode);
|
||||
ASSERT_NOT_REACHED();
|
||||
int rc = syscall(SC_fchmod, fd, mode);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@ -9,6 +10,7 @@ int main(int argc, char** argv)
|
||||
printf("usage: cp <source> <destination>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int src_fd = open(argv[1], O_RDONLY);
|
||||
if (src_fd < 0) {
|
||||
perror("open src");
|
||||
@ -20,6 +22,13 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct stat src_stat;
|
||||
int rc = fstat(src_fd, &src_stat);
|
||||
if (rc < 0) {
|
||||
perror("stat src");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char buffer[BUFSIZ];
|
||||
ssize_t nread = read(src_fd, buffer, sizeof(buffer));
|
||||
@ -42,6 +51,13 @@ int main(int argc, char** argv)
|
||||
bufptr += nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
rc = fchmod(dst_fd, src_stat.st_mode);
|
||||
if (rc < 0) {
|
||||
perror("fchmod dst");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(src_fd);
|
||||
close(dst_fd);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user