mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +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
					
				
					 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
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling