mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 20:45:14 +00:00
Implement utime() along with a naive /bin/touch.
This synchronous approach to inodes is silly, obviously. I need to rework it so that the in-memory CoreInode object is the canonical inode, and then we just need a sync() that flushes pending changes to disk.
This commit is contained in:
parent
e03d341615
commit
038d8641f9
Notes:
sideshowbarker
2024-07-19 16:08:06 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/038d8641f93
22 changed files with 122 additions and 22 deletions
|
@ -1079,6 +1079,30 @@ int Process::sys$close(int fd)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf)
|
||||
{
|
||||
if (!validate_read_str(pathname))
|
||||
return -EFAULT;
|
||||
if (buf && !validate_read_typed(buf))
|
||||
return -EFAULT;
|
||||
String path(pathname);
|
||||
int error;
|
||||
auto descriptor = VFS::the().open(move(path), error, 0, cwd_inode()->identifier());
|
||||
if (!descriptor)
|
||||
return error;
|
||||
Unix::time_t atime;
|
||||
Unix::time_t mtime;
|
||||
if (buf) {
|
||||
atime = buf->actime;
|
||||
mtime = buf->modtime;
|
||||
} else {
|
||||
auto now = RTC::now();
|
||||
mtime = now;
|
||||
atime = now;
|
||||
}
|
||||
return descriptor->set_atime_and_mtime(atime, mtime);
|
||||
}
|
||||
|
||||
int Process::sys$access(const char* pathname, int mode)
|
||||
{
|
||||
(void) mode;
|
||||
|
|
|
@ -173,6 +173,7 @@ public:
|
|||
int sys$ioctl(int fd, unsigned request, unsigned arg);
|
||||
int sys$mkdir(const char* pathname, mode_t mode);
|
||||
Unix::clock_t sys$times(Unix::tms*);
|
||||
int sys$utime(const char* pathname, const struct Unix::utimbuf*);
|
||||
|
||||
static void initialize();
|
||||
|
||||
|
|
|
@ -177,6 +177,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
|||
return current->sys$mkdir((const char*)arg1, (mode_t)arg2);
|
||||
case Syscall::SC_times:
|
||||
return current->sys$times((Unix::tms*)arg1);
|
||||
case Syscall::SC_utime:
|
||||
return current->sys$utime((const char*)arg1, (const Unix::utimbuf*)arg2);
|
||||
default:
|
||||
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
||||
break;
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
__ENUMERATE_SYSCALL(ioctl) \
|
||||
__ENUMERATE_SYSCALL(mkdir) \
|
||||
__ENUMERATE_SYSCALL(times) \
|
||||
__ENUMERATE_SYSCALL(utime) \
|
||||
|
||||
|
||||
#define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
|
||||
|
|
|
@ -30,6 +30,7 @@ cp -v ../Userland/kill mnt/bin/kill
|
|||
cp -v ../Userland/tty mnt/bin/tty
|
||||
cp -v ../Userland/strsignal mnt/bin/strsignal
|
||||
cp -v ../Userland/mkdir mnt/bin/mkdir
|
||||
cp -v ../Userland/touch mnt/bin/touch
|
||||
sh sync-local.sh
|
||||
cp -v kernel.map mnt/
|
||||
ln -s dir_a mnt/dir_cur
|
||||
|
|
|
@ -32,6 +32,7 @@ LIBC_OBJS = \
|
|||
qsort.o \
|
||||
ioctl.o \
|
||||
math.o \
|
||||
utime.o \
|
||||
entry.o
|
||||
|
||||
OBJS = $(AK_OBJS) $(LIBC_OBJS)
|
||||
|
|
14
LibC/utime.cpp
Normal file
14
LibC/utime.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <utime.h>
|
||||
#include <errno.h>
|
||||
#include <Kernel/Syscall.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int utime(const char* pathname, const struct utimbuf* buf)
|
||||
{
|
||||
int rc = Syscall::invoke(Syscall::SC_utime, (dword)pathname, (dword)buf);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
10
LibC/utime.h
10
LibC/utime.h
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int utime(const char* pathname, const struct utimbuf*);
|
||||
|
||||
__END_DECLS
|
||||
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -21,3 +21,4 @@ ft2
|
|||
strsignal
|
||||
fgrep
|
||||
mkdir
|
||||
touch
|
||||
|
|
|
@ -19,7 +19,8 @@ OBJS = \
|
|||
strsignal.o \
|
||||
fgrep.o \
|
||||
tty.o \
|
||||
mkdir.o
|
||||
mkdir.o \
|
||||
touch.o
|
||||
|
||||
APPS = \
|
||||
id \
|
||||
|
@ -42,7 +43,8 @@ APPS = \
|
|||
strsignal \
|
||||
fgrep \
|
||||
tty \
|
||||
mkdir
|
||||
mkdir \
|
||||
touch
|
||||
|
||||
ARCH_FLAGS =
|
||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
||||
|
@ -125,6 +127,9 @@ strsignal: strsignal.o
|
|||
mkdir: mkdir.o
|
||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||
|
||||
touch: touch.o
|
||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||
|
||||
.cpp.o:
|
||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
|
|
|
@ -152,6 +152,8 @@ int do_dir(const char* path)
|
|||
|
||||
printf(" %10u ", st.st_size);
|
||||
|
||||
printf(" %10u ", st.st_mtime);
|
||||
|
||||
print_name(st, de->d_name, pathbuf);
|
||||
|
||||
printf("\n");
|
||||
|
|
16
Userland/touch.cpp
Normal file
16
Userland/touch.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include <utime.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: touch <path>\n");
|
||||
return 1;
|
||||
}
|
||||
int rc = utime(argv[1], nullptr);
|
||||
if (rc < 0)
|
||||
perror("utime");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -716,16 +716,18 @@ bool Ext2FS::modify_link_count(InodeIndex inode, int delta)
|
|||
return write_ext2_inode(inode, *e2inode);
|
||||
}
|
||||
|
||||
bool Ext2FS::set_mtime(InodeIdentifier inode, dword timestamp)
|
||||
int Ext2FS::set_atime_and_mtime(InodeIdentifier inode, dword atime, dword mtime)
|
||||
{
|
||||
ASSERT(inode.fsid() == id());
|
||||
|
||||
auto e2inode = lookup_ext2_inode(inode.index());
|
||||
if (!e2inode)
|
||||
return false;
|
||||
return -EIO;
|
||||
|
||||
kprintf("changing inode %u mtime from %u to %u\n", inode.index(), e2inode->i_mtime, timestamp);
|
||||
e2inode->i_mtime = timestamp;
|
||||
dbgprintf("changing inode %u atime from %u to %u\n", inode.index(), e2inode->i_atime, atime);
|
||||
dbgprintf("changing inode %u mtime from %u to %u\n", inode.index(), e2inode->i_mtime, mtime);
|
||||
e2inode->i_mtime = mtime;
|
||||
e2inode->i_atime = atime;
|
||||
|
||||
return write_ext2_inode(inode.index(), *e2inode);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ private:
|
|||
virtual InodeIdentifier root_inode() const override;
|
||||
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
||||
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) override;
|
||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||
|
|
|
@ -288,3 +288,17 @@ FileDescriptor::FileDescriptor(FIFO& fifo, FIFO::Direction direction)
|
|||
{
|
||||
m_fifo->open(direction);
|
||||
}
|
||||
|
||||
int FileDescriptor::set_atime_and_mtime(time_t atime, time_t mtime)
|
||||
{
|
||||
if (!m_vnode || !m_vnode->core_inode())
|
||||
return -EBADF;
|
||||
return m_vnode->core_inode()->set_atime_and_mtime(atime, mtime);
|
||||
}
|
||||
|
||||
int FileDescriptor::set_ctime(time_t ctime)
|
||||
{
|
||||
(void) ctime;
|
||||
// FIXME: Implement.
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
|
|
@ -64,13 +64,15 @@ public:
|
|||
|
||||
ByteBuffer& generator_cache() { return m_generator_cache; }
|
||||
|
||||
int set_atime_and_mtime(time_t, time_t);
|
||||
int set_ctime(time_t);
|
||||
|
||||
private:
|
||||
friend class VFS;
|
||||
explicit FileDescriptor(RetainPtr<Vnode>&&);
|
||||
FileDescriptor(FIFO&, FIFO::Direction);
|
||||
|
||||
RetainPtr<Vnode> m_vnode;
|
||||
RetainPtr<CoreInode> m_inode;
|
||||
|
||||
Unix::off_t m_current_offset { 0 };
|
||||
|
||||
|
|
|
@ -127,3 +127,8 @@ FS::DirectoryEntry::DirectoryEntry(const char* n, size_t nl, InodeIdentifier i,
|
|||
CoreInode::~CoreInode()
|
||||
{
|
||||
}
|
||||
|
||||
int CoreInode::set_atime_and_mtime(Unix::time_t atime, Unix::time_t mtime)
|
||||
{
|
||||
return fs().set_atime_and_mtime(identifier(), atime, mtime);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
byte fileType { 0 };
|
||||
};
|
||||
|
||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0;
|
||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) = 0;
|
||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) = 0;
|
||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) = 0;
|
||||
|
||||
|
@ -85,6 +85,8 @@ public:
|
|||
virtual InodeIdentifier lookup(const String& name) = 0;
|
||||
virtual String reverse_lookup(InodeIdentifier) = 0;
|
||||
|
||||
int set_atime_and_mtime(Unix::time_t atime, Unix::time_t mtime);
|
||||
|
||||
protected:
|
||||
CoreInode(FS& fs, unsigned index)
|
||||
: m_fs(fs)
|
||||
|
|
|
@ -146,11 +146,12 @@ InodeMetadata SynthFS::inode_metadata(InodeIdentifier inode) const
|
|||
return (*it).value->m_metadata;
|
||||
}
|
||||
|
||||
bool SynthFS::set_mtime(InodeIdentifier, dword timestamp)
|
||||
int SynthFS::set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime)
|
||||
{
|
||||
(void) timestamp;
|
||||
(void) atime;
|
||||
(void) mtime;
|
||||
kprintf("FIXME: Implement SyntheticFileSystem::setModificationTime().\n");
|
||||
return false;
|
||||
return -ENOTIMPL;
|
||||
}
|
||||
|
||||
InodeIdentifier SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
virtual InodeIdentifier root_inode() const override;
|
||||
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
||||
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) override;
|
||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||
|
|
|
@ -264,6 +264,11 @@ typedef signed_qword off_t;
|
|||
typedef ::time_t time_t;
|
||||
#endif
|
||||
|
||||
struct utimbuf {
|
||||
time_t actime;
|
||||
time_t modtime;
|
||||
};
|
||||
|
||||
typedef dword blksize_t;
|
||||
typedef dword blkcnt_t;
|
||||
|
||||
|
|
|
@ -252,15 +252,6 @@ void VFS::traverse_directory_inode(CoreInode& dir_inode, Function<bool(const FS:
|
|||
});
|
||||
}
|
||||
|
||||
bool VFS::touch(const String& path)
|
||||
{
|
||||
int error;
|
||||
auto inode = resolve_path(path, root_inode_id(), error);
|
||||
if (!inode.is_valid())
|
||||
return false;
|
||||
return inode.fs()->set_mtime(inode, ktime(nullptr));
|
||||
}
|
||||
|
||||
RetainPtr<FileDescriptor> VFS::open(CharacterDevice& device, int options)
|
||||
{
|
||||
// FIXME: Respect options.
|
||||
|
|
Loading…
Add table
Reference in a new issue