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:
Andreas Kling 2018-12-19 21:14:55 +01:00
parent e03d341615
commit 038d8641f9
Notes: sideshowbarker 2024-07-19 16:08:06 +09:00
22 changed files with 122 additions and 22 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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