diff --git a/repos/libports/include/libc-plugin/fd_alloc.h b/repos/libports/include/libc-plugin/fd_alloc.h index 743c9df13..e03dfa739 100644 --- a/repos/libports/include/libc-plugin/fd_alloc.h +++ b/repos/libports/include/libc-plugin/fd_alloc.h @@ -53,8 +53,9 @@ namespace Libc { Plugin *plugin; Plugin_context *context; - int flags = 0; /* for 'fcntl' */ - bool cloexec = 0; /* for 'fcntl' */ + int flags = 0; /* for 'fcntl' */ + bool cloexec = 0; /* for 'fcntl' */ + bool modified = false; File_descriptor(Id_space &id_space, Plugin &plugin, Plugin_context &context) : _elem(*this, id_space), plugin(&plugin), context(&context) { } diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index a6d37fadb..e5be14385 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -452,8 +452,11 @@ int Libc::Vfs_plugin::_vfs_sync(Vfs::Vfs_handle &vfs_handle) int Libc::Vfs_plugin::close(File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); - /* XXX: mark the handle as requiring sync or not */ - _vfs_sync(*handle); + + if ((fd->modified) || (fd->flags & O_CREAT)) { + _vfs_sync(*handle); + } + VFS_THREAD_SAFE(handle->close()); file_descriptor_allocator()->free(fd); return 0; @@ -515,7 +518,10 @@ Libc::File_descriptor *Libc::Vfs_plugin::dup(File_descriptor *fd) int Libc::Vfs_plugin::fstat(File_descriptor *fd, struct stat *buf) { Vfs::Vfs_handle *handle = vfs_handle(fd); - _vfs_sync(*handle); + if (fd->modified) { + _vfs_sync(*handle); + fd->modified = false; + } return stat(fd->fd_path, buf); } @@ -587,6 +593,10 @@ ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf, { typedef Vfs::File_io_service::Write_result Result; + if ((fd->flags & O_ACCMODE) == O_RDONLY) { + return Errno(EBADF); + } + Vfs::Vfs_handle *handle = vfs_handle(fd); Vfs::file_size out_count = 0; @@ -651,6 +661,7 @@ ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf, } VFS_THREAD_SAFE(handle->advance_seek(out_count)); + fd->modified = true; return out_count; } @@ -661,6 +672,10 @@ ssize_t Libc::Vfs_plugin::read(File_descriptor *fd, void *buf, { dispatch_pending_io_signals(); + if ((fd->flags & O_ACCMODE) == O_WRONLY) { + return Errno(EBADF); + } + typedef Vfs::File_io_service::Read_result Result; Vfs::Vfs_handle *handle = vfs_handle(fd); @@ -1045,7 +1060,10 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, int request, char *argp) int Libc::Vfs_plugin::ftruncate(File_descriptor *fd, ::off_t length) { Vfs::Vfs_handle *handle = vfs_handle(fd); - _vfs_sync(*handle); + if (fd->modified) { + _vfs_sync(*handle); + fd->modified = false; + } typedef Vfs::File_io_service::Ftruncate_result Result; @@ -1101,7 +1119,15 @@ int Libc::Vfs_plugin::fcntl(File_descriptor *fd, int cmd, long arg) int Libc::Vfs_plugin::fsync(File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); - return _vfs_sync(*handle); + if (!fd->modified) { return 0; } + + /* + * XXX checking the return value of _vfs_sync amd returning -1 + * in the EIO case will break the lighttpd or rather the socket_fs + */ + fd->modified = !!_vfs_sync(*handle); + + return 0; }