Просмотр исходного кода

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.
Andreas Kling 6 лет назад
Родитель
Сommit
038d8641f9

+ 24 - 0
Kernel/Process.cpp

@@ -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;

+ 1 - 0
Kernel/Process.h

@@ -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();
 

+ 2 - 0
Kernel/Syscall.cpp

@@ -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;

+ 1 - 0
Kernel/Syscall.h

@@ -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))

+ 1 - 0
Kernel/sync.sh

@@ -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

+ 1 - 0
LibC/Makefile

@@ -32,6 +32,7 @@ LIBC_OBJS = \
        qsort.o \
        ioctl.o \
        math.o \
+       utime.o \
        entry.o
 
 OBJS = $(AK_OBJS) $(LIBC_OBJS)

+ 14 - 0
LibC/utime.cpp

@@ -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 - 0
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 - 0
Userland/.gitignore

@@ -21,3 +21,4 @@ ft2
 strsignal
 fgrep
 mkdir
+touch

+ 7 - 2
Userland/Makefile

@@ -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 $<
 

+ 2 - 0
Userland/ls.cpp

@@ -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 - 0
Userland/touch.cpp

@@ -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;
+}
+

+ 6 - 4
VirtualFileSystem/Ext2FileSystem.cpp

@@ -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);
 }

+ 1 - 1
VirtualFileSystem/Ext2FileSystem.h

@@ -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;

+ 14 - 0
VirtualFileSystem/FileDescriptor.cpp

@@ -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();
+}

+ 3 - 1
VirtualFileSystem/FileDescriptor.h

@@ -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 };
 

+ 5 - 0
VirtualFileSystem/FileSystem.cpp

@@ -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);
+}

+ 3 - 1
VirtualFileSystem/FileSystem.h

@@ -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)

+ 4 - 3
VirtualFileSystem/SyntheticFileSystem.cpp

@@ -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)

+ 1 - 1
VirtualFileSystem/SyntheticFileSystem.h

@@ -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;

+ 5 - 0
VirtualFileSystem/UnixTypes.h

@@ -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;
 

+ 0 - 9
VirtualFileSystem/VirtualFileSystem.cpp

@@ -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.