mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:08:12 +00:00
Kernel+Userland: Add the rename() syscall along with a basic /bin/mv.
This commit is contained in:
parent
71b6436552
commit
37ae00a4dd
11 changed files with 99 additions and 2 deletions
|
@ -312,6 +312,50 @@ KResult VFS::chmod(const String& path, mode_t mode, Inode& base)
|
||||||
return chmod(*inode, mode);
|
return chmod(*inode, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResult VFS::rename(const String& old_path, const String& new_path, Inode& base)
|
||||||
|
{
|
||||||
|
RetainPtr<Inode> old_parent_inode;
|
||||||
|
auto old_inode_or_error = resolve_path_to_inode(old_path, base, &old_parent_inode);
|
||||||
|
if (old_inode_or_error.is_error())
|
||||||
|
return old_inode_or_error.error();
|
||||||
|
auto old_inode = old_inode_or_error.value();
|
||||||
|
|
||||||
|
RetainPtr<Inode> new_parent_inode;
|
||||||
|
auto new_inode_or_error = resolve_path_to_inode(new_path, base, &new_parent_inode);
|
||||||
|
if (new_inode_or_error.is_error()) {
|
||||||
|
if (new_inode_or_error.error() != -ENOENT)
|
||||||
|
return new_inode_or_error.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_parent_inode->metadata().may_write(current->process()))
|
||||||
|
return KResult(-EACCES);
|
||||||
|
|
||||||
|
if (!old_parent_inode->metadata().may_write(current->process()))
|
||||||
|
return KResult(-EACCES);
|
||||||
|
|
||||||
|
if (!new_inode_or_error.is_error()) {
|
||||||
|
auto new_inode = new_inode_or_error.value();
|
||||||
|
// FIXME: Is this really correct? Check what other systems do.
|
||||||
|
if (new_inode.ptr() == old_inode.ptr())
|
||||||
|
return KSuccess;
|
||||||
|
if (new_inode->is_directory() && !old_inode->is_directory())
|
||||||
|
return KResult(-EISDIR);
|
||||||
|
auto result = new_parent_inode->remove_child(new_parent_inode->reverse_lookup(new_inode->identifier()));
|
||||||
|
if (result.is_error())
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = new_parent_inode->add_child(old_inode->identifier(), FileSystemPath(new_path).basename(), 0 /* FIXME: file type? */);
|
||||||
|
if (result.is_error())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = old_parent_inode->remove_child(old_parent_inode->reverse_lookup(old_inode->identifier()));
|
||||||
|
if (result.is_error())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
KResult VFS::chown(const String& path, uid_t a_uid, gid_t a_gid, Inode& base)
|
KResult VFS::chown(const String& path, uid_t a_uid, gid_t a_gid, Inode& base)
|
||||||
{
|
{
|
||||||
auto inode_or_error = resolve_path_to_inode(path, base);
|
auto inode_or_error = resolve_path_to_inode(path, base);
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
KResult access(const String& path, int mode, Inode& base);
|
KResult access(const String& path, int mode, Inode& base);
|
||||||
KResult stat(const String& path, int options, Inode& base, struct stat&);
|
KResult stat(const String& path, int options, Inode& base, struct stat&);
|
||||||
KResult utime(const String& path, Inode& base, time_t atime, time_t mtime);
|
KResult utime(const String& path, Inode& base, time_t atime, time_t mtime);
|
||||||
|
KResult rename(const String& oldpath, const String& newpath, Inode& base);
|
||||||
KResultOr<Retained<Inode>> open_directory(const String& path, Inode& base);
|
KResultOr<Retained<Inode>> open_directory(const String& path, Inode& base);
|
||||||
|
|
||||||
void register_device(Device&);
|
void register_device(Device&);
|
||||||
|
|
|
@ -2445,3 +2445,12 @@ int Process::sys$donate(int tid)
|
||||||
Scheduler::donate_to(beneficiary, "sys$donate");
|
Scheduler::donate_to(beneficiary, "sys$donate");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Process::sys$rename(const char* oldpath, const char* newpath)
|
||||||
|
{
|
||||||
|
if (!validate_read_str(oldpath))
|
||||||
|
return -EFAULT;
|
||||||
|
if (!validate_read_str(newpath))
|
||||||
|
return -EFAULT;
|
||||||
|
return VFS::the().rename(String(oldpath), String(newpath), cwd_inode());
|
||||||
|
}
|
||||||
|
|
|
@ -180,6 +180,7 @@ public:
|
||||||
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
|
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
|
||||||
int sys$restore_signal_mask(dword mask);
|
int sys$restore_signal_mask(dword mask);
|
||||||
int sys$create_thread(int(*)(void*), void*);
|
int sys$create_thread(int(*)(void*), void*);
|
||||||
|
int sys$rename(const char* oldpath, const char* newpath);
|
||||||
|
|
||||||
int sys$create_shared_buffer(pid_t peer_pid, int, void** buffer);
|
int sys$create_shared_buffer(pid_t peer_pid, int, void** buffer);
|
||||||
void* sys$get_shared_buffer(int shared_buffer_id);
|
void* sys$get_shared_buffer(int shared_buffer_id);
|
||||||
|
|
|
@ -241,6 +241,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
||||||
return current->process().sys$setsockopt((const SC_setsockopt_params*)arg1);
|
return current->process().sys$setsockopt((const SC_setsockopt_params*)arg1);
|
||||||
case Syscall::SC_create_thread:
|
case Syscall::SC_create_thread:
|
||||||
return current->process().sys$create_thread((int(*)(void*))arg1, (void*)arg2);
|
return current->process().sys$create_thread((int(*)(void*))arg1, (void*)arg2);
|
||||||
|
case Syscall::SC_rename:
|
||||||
|
return current->process().sys$rename((const char*)arg1, (const char*)arg2);
|
||||||
default:
|
default:
|
||||||
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -95,6 +95,7 @@
|
||||||
__ENUMERATE_SYSCALL(create_thread) \
|
__ENUMERATE_SYSCALL(create_thread) \
|
||||||
__ENUMERATE_SYSCALL(gettid) \
|
__ENUMERATE_SYSCALL(gettid) \
|
||||||
__ENUMERATE_SYSCALL(donate) \
|
__ENUMERATE_SYSCALL(donate) \
|
||||||
|
__ENUMERATE_SYSCALL(rename) \
|
||||||
|
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
|
@ -79,6 +79,7 @@ cp -v ../Userland/uc mnt/bin/uc
|
||||||
cp -v ../Userland/tc mnt/bin/tc
|
cp -v ../Userland/tc mnt/bin/tc
|
||||||
cp -v ../Userland/host mnt/bin/host
|
cp -v ../Userland/host mnt/bin/host
|
||||||
cp -v ../Userland/qs mnt/bin/qs
|
cp -v ../Userland/qs mnt/bin/qs
|
||||||
|
cp -v ../Userland/mv mnt/bin/mv
|
||||||
chmod 4755 mnt/bin/su
|
chmod 4755 mnt/bin/su
|
||||||
cp -v ../Applications/Terminal/Terminal mnt/bin/Terminal
|
cp -v ../Applications/Terminal/Terminal mnt/bin/Terminal
|
||||||
cp -v ../Applications/FontEditor/FontEditor mnt/bin/FontEditor
|
cp -v ../Applications/FontEditor/FontEditor mnt/bin/FontEditor
|
||||||
|
|
|
@ -418,8 +418,8 @@ int fclose(FILE* stream)
|
||||||
|
|
||||||
int rename(const char* oldpath, const char* newpath)
|
int rename(const char* oldpath, const char* newpath)
|
||||||
{
|
{
|
||||||
dbgprintf("FIXME(LibC): rename(%s, %s)\n", oldpath, newpath);
|
int rc = syscall(SC_rename, oldpath, newpath);
|
||||||
ASSERT_NOT_REACHED();
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* tmpnam(char*)
|
char* tmpnam(char*)
|
||||||
|
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -42,3 +42,4 @@ uc
|
||||||
tc
|
tc
|
||||||
host
|
host
|
||||||
qs
|
qs
|
||||||
|
mv
|
||||||
|
|
|
@ -38,6 +38,7 @@ OBJS = \
|
||||||
tc.o \
|
tc.o \
|
||||||
host.o \
|
host.o \
|
||||||
qs.o \
|
qs.o \
|
||||||
|
mv.o \
|
||||||
rm.o
|
rm.o
|
||||||
|
|
||||||
APPS = \
|
APPS = \
|
||||||
|
@ -81,6 +82,7 @@ APPS = \
|
||||||
tc \
|
tc \
|
||||||
host \
|
host \
|
||||||
qs \
|
qs \
|
||||||
|
mv \
|
||||||
rm
|
rm
|
||||||
|
|
||||||
ARCH_FLAGS =
|
ARCH_FLAGS =
|
||||||
|
@ -223,6 +225,9 @@ host: host.o
|
||||||
qs: qs.o
|
qs: qs.o
|
||||||
$(LD) -o $@ $(LDFLAGS) -L../LibGUI $< -lgui -lc
|
$(LD) -o $@ $(LDFLAGS) -L../LibGUI $< -lgui -lc
|
||||||
|
|
||||||
|
mv: mv.o
|
||||||
|
$(LD) -o $@ $(LDFLAGS) -L../LibGUI $< -lgui -lc
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
|
32
Userland/mv.cpp
Normal file
32
Userland/mv.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <AK/AKString.h>
|
||||||
|
#include <AK/FileSystemPath.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("usage: mv <old-path> <new-path>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
String old_path = argv[1];
|
||||||
|
String new_path = argv[2];
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
int rc = lstat(new_path.characters(), &st);
|
||||||
|
if (rc == 0) {
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
auto old_basename = FileSystemPath(old_path).basename();
|
||||||
|
new_path = String::format("%s/%s", new_path.characters(), old_basename.characters());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rename(old_path.characters(), new_path.characters());
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("rename");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue