1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:17:34 +00:00

Implement basic chmod() syscall and /bin/chmod helper.

Only raw octal modes are supported right now.
This patch also changes mode_t from 32-bit to 16-bit to match the on-disk
type used by Ext2FS.

I also ran into EPERM being errno=0 which was confusing, so I inserted an
ESUCCESS in its place.
This commit is contained in:
Andreas Kling 2019-01-29 04:55:08 +01:00
parent ad53f6afd3
commit c30e2c8d44
22 changed files with 156 additions and 4 deletions

View file

@ -1292,3 +1292,13 @@ size_t Ext2FSInode::directory_entry_count() const
LOCKER(m_lock);
return m_lookup_cache.size();
}
bool Ext2FSInode::chmod(mode_t mode, int& error)
{
error = 0;
if (m_raw_inode.i_mode == mode)
return true;
m_raw_inode.i_mode = mode;
set_metadata_dirty(true);
return true;
}

View file

@ -41,6 +41,7 @@ private:
virtual int increment_link_count() override;
virtual int decrement_link_count() override;
virtual size_t directory_entry_count() const override;
virtual bool chmod(mode_t, int& error) override;
void populate_lookup_cache() const;

View file

@ -74,6 +74,7 @@ public:
bool is_symlink() const { return metadata().isSymbolicLink(); }
bool is_directory() const { return metadata().isDirectory(); }
bool is_character_device() const { return metadata().isCharacterDevice(); }
mode_t mode() const { return metadata().mode; }
InodeIdentifier identifier() const { return { fsid(), index() }; }
virtual InodeMetadata metadata() const = 0;
@ -89,6 +90,7 @@ public:
virtual bool remove_child(const String& name, int& error) = 0;
virtual RetainPtr<Inode> parent() const = 0;
virtual size_t directory_entry_count() const = 0;
virtual bool chmod(mode_t, int& error) = 0;
bool is_metadata_dirty() const { return m_metadata_dirty; }

View file

@ -2120,3 +2120,13 @@ int Process::sys$read_tsc(dword* lsw, dword* msw)
read_tsc(*lsw, *msw);
return 0;
}
int Process::sys$chmod(const char* pathname, mode_t mode)
{
if (!validate_read_str(pathname))
return -EFAULT;
int error;
if (!VFS::the().chmod(String(pathname), mode, *cwd_inode(), error))
return error;
return 0;
}

View file

@ -196,6 +196,7 @@ public:
int sys$unlink(const char* pathname);
int sys$rmdir(const char* pathname);
int sys$read_tsc(dword* lsw, dword* msw);
int sys$chmod(const char* pathname, mode_t);
int gui$create_window(const GUI_WindowParameters*);
int gui$destroy_window(int window_id);

View file

@ -312,3 +312,9 @@ size_t SynthFSInode::directory_entry_count() const
// NOTE: The 2 is for '.' and '..'
return m_children.size() + 2;
}
bool SynthFSInode::chmod(mode_t, int& error)
{
error = -EPERM;
return false;
}

View file

@ -65,6 +65,7 @@ private:
virtual bool remove_child(const String& name, int& error) override;
virtual RetainPtr<Inode> parent() const override;
virtual size_t directory_entry_count() const override;
virtual bool chmod(mode_t, int& error) override;
SynthFS& fs();
const SynthFS& fs() const;

View file

@ -221,6 +221,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->gui$set_global_cursor_tracking_enabled((int)arg1, (bool)arg2);
case Syscall::SC_rmdir:
return current->sys$rmdir((const char*)arg1);
case Syscall::SC_chmod:
return current->sys$chmod((const char*)arg1, (mode_t)arg2);
default:
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
break;

View file

@ -83,6 +83,7 @@
__ENUMERATE_SYSCALL(gui_notify_paint_finished) \
__ENUMERATE_SYSCALL(gui_set_global_cursor_tracking_enabled) \
__ENUMERATE_SYSCALL(rmdir) \
__ENUMERATE_SYSCALL(chmod) \
#ifdef SERENITY

View file

@ -214,7 +214,7 @@ struct winsize {
typedef dword dev_t;
typedef dword ino_t;
typedef dword mode_t;
typedef word mode_t;
typedef dword nlink_t;
typedef dword uid_t;
typedef dword gid_t;

View file

@ -228,6 +228,37 @@ bool VFS::mkdir(const String& path, mode_t mode, InodeIdentifier base, int& erro
return false;
}
bool VFS::chmod(const String& path, mode_t mode, Inode& base, int& error)
{
error = -EWHYTHO;
// FIXME: This won't work nicely across mount boundaries.
FileSystemPath p(path);
if (!p.is_valid()) {
error = -EINVAL;
return false;
}
InodeIdentifier parent_dir;
auto inode_id = resolve_path(path, base.identifier(), error, 0, &parent_dir);
if (!inode_id.is_valid()) {
error = -ENOENT;
return false;
}
auto inode = get_inode(inode_id);
// FIXME: Permission checks.
// Only change the permission bits.
mode = (inode->mode() & ~04777) | (mode & 04777);
kprintf("VFS::chmod(): %u:%u mode %o\n", inode_id.fsid(), inode_id.index(), mode);
if (!inode->chmod(mode, error))
return false;
error = 0;
return true;
}
bool VFS::unlink(const String& path, Inode& base, int& error)
{
error = -EWHYTHO;

View file

@ -69,6 +69,7 @@ public:
bool mkdir(const String& path, mode_t mode, InodeIdentifier base, int& error);
bool unlink(const String& path, Inode& base, int& error);
bool rmdir(const String& path, Inode& base, int& error);
bool chmod(const String& path, mode_t, Inode& base, int& error);
void register_character_device(CharacterDevice&);

View file

@ -50,6 +50,7 @@ cp -v ../Userland/guitest2 mnt/bin/guitest2
cp -v ../Userland/sysctl mnt/bin/sysctl
cp -v ../Terminal/Terminal mnt/bin/Terminal
cp -v ../Userland/dmesg mnt/bin/dmesg
cp -v ../Userland/chmod mnt/bin/chmod
sh sync-local.sh
cp -v kernel.map mnt/
ln -s dir_a mnt/dir_cur

View file

@ -37,7 +37,7 @@ typedef dword ino_t;
typedef signed_dword off_t;
typedef dword dev_t;
typedef dword mode_t;
typedef word mode_t;
typedef dword nlink_t;
typedef dword blksize_t;
typedef dword blkcnt_t;