1.1 --- a/libfsclient/include/fsclient/client.h Thu Feb 24 22:35:00 2022 +0100 1.2 +++ b/libfsclient/include/fsclient/client.h Fri Feb 25 18:45:11 2022 +0100 1.3 @@ -49,12 +49,15 @@ 1.4 1.5 /* Other file operations. */ 1.6 1.7 -long client_remove(const char *name); 1.8 -long client_remove_using(const char *name, l4_cap_idx_t server); 1.9 +long client_remove(const char *path); 1.10 +long client_remove_using(const char *path, l4_cap_idx_t server); 1.11 1.12 long client_rename(const char *source, const char *target); 1.13 long client_rename_using(const char *source, const char *target, l4_cap_idx_t server); 1.14 1.15 +long client_stat(const char *path, struct stat *st); 1.16 +long client_stat_using(const char *path, struct stat *st, l4_cap_idx_t server); 1.17 + 1.18 /* File and region operations. */ 1.19 1.20 long client_flush(file_t *file);
2.1 --- a/libfsclient/include/fsclient/file.h Thu Feb 24 22:35:00 2022 +0100 2.2 +++ b/libfsclient/include/fsclient/file.h Fri Feb 25 18:45:11 2022 +0100 2.3 @@ -21,6 +21,8 @@ 2.4 2.5 #pragma once 2.6 2.7 +#include <sys/stat.h> 2.8 + 2.9 #include <l4/sys/types.h> 2.10 2.11 #include <systypes/base.h> 2.12 @@ -86,6 +88,7 @@ 2.13 long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server); 2.14 long file_remove(const char *filename, l4_cap_idx_t server); 2.15 long file_rename(const char *source, const char *target, l4_cap_idx_t server); 2.16 +long file_stat(const char *filename, struct stat *st, l4_cap_idx_t server); 2.17 2.18 /* File lifecycle operations. */ 2.19 2.20 @@ -93,6 +96,7 @@ 2.21 long file_context_open(file_t *file, flags_t flags, file_t *context); 2.22 long file_context_remove(file_t *context); 2.23 long file_context_rename(file_t *context); 2.24 +long file_context_stat(struct stat *st, file_t *context); 2.25 void file_init(file_t *file); 2.26 2.27 /* File and region operations. */
3.1 --- a/libfsclient/lib/src/client.cc Thu Feb 24 22:35:00 2022 +0100 3.2 +++ b/libfsclient/lib/src/client.cc Fri Feb 25 18:45:11 2022 +0100 3.3 @@ -361,18 +361,18 @@ 3.4 3.5 /* Remove a file from the filesystem. */ 3.6 3.7 -long client_remove(const char *name) 3.8 +long client_remove(const char *path) 3.9 { 3.10 l4_cap_idx_t server = l4re_env_get_cap("server"); 3.11 3.12 - return client_remove_using(name, server); 3.13 + return client_remove_using(path, server); 3.14 } 3.15 3.16 /* Remove a file from the filesystem via a named capability. */ 3.17 3.18 -long client_remove_using(const char *name, l4_cap_idx_t server) 3.19 +long client_remove_using(const char *path, l4_cap_idx_t server) 3.20 { 3.21 - return file_remove(name, server); 3.22 + return file_remove(path, server); 3.23 } 3.24 3.25 3.26 @@ -395,6 +395,24 @@ 3.27 3.28 3.29 3.30 +/* Obtain filesystem object statistics. */ 3.31 + 3.32 +long client_stat(const char *path, struct stat *st) 3.33 +{ 3.34 + l4_cap_idx_t server = l4re_env_get_cap("server"); 3.35 + 3.36 + return client_stat_using(path, st, server); 3.37 +} 3.38 + 3.39 +/* Obtain object statistics from the filesystem via a named capability. */ 3.40 + 3.41 +long client_stat_using(const char *path, struct stat *st, l4_cap_idx_t server) 3.42 +{ 3.43 + return file_stat(path, st, server); 3.44 +} 3.45 + 3.46 + 3.47 + 3.48 /* Obtain the current region of a pipe. */ 3.49 3.50 long client_current_region(file_t *file)
4.1 --- a/libfsclient/lib/src/file.cc Thu Feb 24 22:35:00 2022 +0100 4.2 +++ b/libfsclient/lib/src/file.cc Fri Feb 25 18:45:11 2022 +0100 4.3 @@ -189,6 +189,31 @@ 4.4 return err; 4.5 } 4.6 4.7 +/* Obtain filesystem object statistics. This is a convenience function invoking 4.8 + file_context and file_context_stat. */ 4.9 + 4.10 +long file_stat(const char *filename, struct stat *st, l4_cap_idx_t server) 4.11 +{ 4.12 + file_t context; 4.13 + offset_t written; 4.14 + long err; 4.15 + 4.16 + err = file_context(&context, server); 4.17 + if (err) 4.18 + return err; 4.19 + 4.20 + if (!file_string_set(&context, filename, 0, &written)) 4.21 + return -L4_ENOMEM; 4.22 + 4.23 + err = file_context_stat(st, &context); 4.24 + 4.25 + /* Close the context, although a separate mechanism could permit contexts to 4.26 + rename several files. */ 4.27 + 4.28 + file_close(&context); 4.29 + return err; 4.30 +} 4.31 + 4.32 4.33 4.34 /* Initialise a file structure for a context obtained from the given server 4.35 @@ -247,6 +272,20 @@ 4.36 return openercontext.rename(); 4.37 } 4.38 4.39 +/* Obtain filesystem object statistics using the given context. */ 4.40 + 4.41 +long file_context_stat(struct stat *st, file_t *context) 4.42 +{ 4.43 + client_OpenerContext openercontext(context->ref); 4.44 + long err = openercontext.stat(); 4.45 + 4.46 + if (err) 4.47 + return err; 4.48 + 4.49 + memcpy(st, context->memory, sizeof(struct stat)); 4.50 + return L4_EOK; 4.51 +} 4.52 + 4.53 4.54 4.55 /* Flush populated data and obtain an updated file size and populated data
5.1 --- a/libfsserver/include/fsserver/ext2_file_opener.h Thu Feb 24 22:35:00 2022 +0100 5.2 +++ b/libfsserver/include/fsserver/ext2_file_opener.h Fri Feb 25 18:45:11 2022 +0100 5.3 @@ -68,6 +68,8 @@ 5.4 5.5 virtual long rename_object(const char *source, const char *target); 5.6 5.7 + virtual long stat_object(const char *path, void *base, offset_t size); 5.8 + 5.9 virtual long unlink_object(fileid_t parent_fileid, fileid_t fileid); 5.10 }; 5.11
6.1 --- a/libfsserver/include/fsserver/ext2_file_operations.h Thu Feb 24 22:35:00 2022 +0100 6.2 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Fri Feb 25 18:45:11 2022 +0100 6.3 @@ -23,6 +23,8 @@ 6.4 6.5 #include <mutex> 6.6 6.7 +#include <sys/stat.h> 6.8 + 6.9 #include <ext2fs/ext2fs.h> 6.10 6.11 #include <systypes/base.h> 6.12 @@ -98,13 +100,15 @@ 6.13 6.14 void write_file(ext2_file_t file, offset_t filepos, const void *addr, offset_t size); 6.15 6.16 - /* Directory access. */ 6.17 + /* Directory and metadata access. */ 6.18 6.19 long directory_iterate(ext2_ino_t dir, 6.20 int func(struct ext2_dir_entry *, int, int, char *, void *), 6.21 void *priv_data); 6.22 6.23 - long read_inode(ext2_ino_t ino_file, struct ext2_inode *inode); 6.24 + long read_inode(ext2_ino_t ino, struct ext2_inode *inode); 6.25 + 6.26 + long stat_inode(ext2_ino_t ino, struct stat *st); 6.27 6.28 /* Callback method. */ 6.29
7.1 --- a/libfsserver/include/fsserver/file_opening.h Thu Feb 24 22:35:00 2022 +0100 7.2 +++ b/libfsserver/include/fsserver/file_opening.h Fri Feb 25 18:45:11 2022 +0100 7.3 @@ -47,6 +47,8 @@ 7.4 virtual long make_directory_accessor(flags_t flags, fileid_t fileid, 7.5 DirectoryAccessor **accessor) = 0; 7.6 7.7 + virtual long stat_object(const char *path, void *base, offset_t size) = 0; 7.8 + 7.9 virtual long remove_object(fileid_t fileid) = 0; 7.10 7.11 virtual long rename_object(const char *source, const char *target) = 0;
8.1 --- a/libfsserver/include/fsserver/host_file_opener.h Thu Feb 24 22:35:00 2022 +0100 8.2 +++ b/libfsserver/include/fsserver/host_file_opener.h Fri Feb 25 18:45:11 2022 +0100 8.3 @@ -82,6 +82,8 @@ 8.4 8.5 virtual long rename_object(const char *source, const char *target); 8.6 8.7 + virtual long stat_object(const char *path, void *base, offset_t size); 8.8 + 8.9 virtual long unlink_object(fileid_t parent_fileid, fileid_t fileid); 8.10 }; 8.11
9.1 --- a/libfsserver/include/fsserver/opener_context_resource.h Thu Feb 24 22:35:00 2022 +0100 9.2 +++ b/libfsserver/include/fsserver/opener_context_resource.h Fri Feb 25 18:45:11 2022 +0100 9.3 @@ -64,6 +64,8 @@ 9.4 9.5 long rename(); 9.6 9.7 + long stat(); 9.8 + 9.9 /* Pager/dataspace methods. */ 9.10 9.11 long map(unsigned long offset, address_t hot_spot, map_flags_t flags,
10.1 --- a/libfsserver/include/fsserver/opener_resource.h Thu Feb 24 22:35:00 2022 +0100 10.2 +++ b/libfsserver/include/fsserver/opener_resource.h Fri Feb 25 18:45:11 2022 +0100 10.3 @@ -63,6 +63,8 @@ 10.4 10.5 long rename(const char *source, const char *target); 10.6 10.7 + long stat(const char *path, void *base, offset_t size); 10.8 + 10.9 /* Opener interface methods. */ 10.10 10.11 long context(l4_cap_idx_t *context);
11.1 --- a/libfsserver/include/fsserver/test_file_opener.h Thu Feb 24 22:35:00 2022 +0100 11.2 +++ b/libfsserver/include/fsserver/test_file_opener.h Fri Feb 25 18:45:11 2022 +0100 11.3 @@ -59,6 +59,8 @@ 11.4 11.5 virtual long rename_object(const char *source, const char *target); 11.6 11.7 + virtual long stat_object(const char *path, void *base, offset_t size); 11.8 + 11.9 virtual long unlink_object(fileid_t parent_fileid, fileid_t fileid); 11.10 }; 11.11
12.1 --- a/libfsserver/lib/files/ext2_file_opener.cc Thu Feb 24 22:35:00 2022 +0100 12.2 +++ b/libfsserver/lib/files/ext2_file_opener.cc Fri Feb 25 18:45:11 2022 +0100 12.3 @@ -129,6 +129,23 @@ 12.4 return L4_EOK; 12.5 } 12.6 12.7 +/* Populate a memory region with statistics metadata for a filesystem object. */ 12.8 + 12.9 +long Ext2FileOpener::stat_object(const char *path, void *base, offset_t size) 12.10 +{ 12.11 + struct stat *st = (struct stat *) base; 12.12 + fileid_t fileid; 12.13 + long err = get_fileid(path, 0, &fileid); 12.14 + 12.15 + if (err) 12.16 + return err; 12.17 + 12.18 + if (sizeof(struct stat) > size) 12.19 + return -L4_ENOMEM; 12.20 + 12.21 + return _ops->stat_inode((ext2_ino_t) fileid, st); 12.22 +} 12.23 + 12.24 /* Remove a filesystem object. */ 12.25 12.26 long Ext2FileOpener::remove_object(fileid_t fileid)
13.1 --- a/libfsserver/lib/files/ext2_file_operations.cc Thu Feb 24 22:35:00 2022 +0100 13.2 +++ b/libfsserver/lib/files/ext2_file_operations.cc Fri Feb 25 18:45:11 2022 +0100 13.3 @@ -252,6 +252,18 @@ 13.4 return L4_EOK; 13.5 } 13.6 13.7 +/* Obtain stat-based information for the given inode. */ 13.8 + 13.9 +long Ext2FileOperations::stat_inode(ext2_ino_t ino, struct stat *st) 13.10 +{ 13.11 + std::lock_guard<std::mutex> guard(_lock); 13.12 + 13.13 + if (image_stat_inode(_fs, ino, st)) 13.14 + return -L4_EIO; 13.15 + 13.16 + return L4_EOK; 13.17 +} 13.18 + 13.19 13.20 13.21 /* Directory iteration support. */
14.1 --- a/libfsserver/lib/files/host_file_opener.cc Thu Feb 24 22:35:00 2022 +0100 14.2 +++ b/libfsserver/lib/files/host_file_opener.cc Fri Feb 25 18:45:11 2022 +0100 14.3 @@ -49,7 +49,7 @@ 14.4 14.5 struct stat st; 14.6 14.7 - if (stat(path, &st)) 14.8 + if (::stat(path, &st)) 14.9 return false; 14.10 14.11 return (st.st_mode & S_IFDIR) ? true : false; 14.12 @@ -65,7 +65,7 @@ 14.13 if (path == NULL) 14.14 return false; 14.15 14.16 - if (stat(path, &st)) 14.17 + if (::stat(path, &st)) 14.18 return false; 14.19 14.20 return (st.st_mode & S_IFREG) ? true : false; 14.21 @@ -196,6 +196,18 @@ 14.22 return L4_EOK; 14.23 } 14.24 14.25 +/* Populate a memory region with statistics metadata for a filesystem object. */ 14.26 + 14.27 +long HostFileOpener::stat_object(const char *path, void *base, offset_t size) 14.28 +{ 14.29 + struct stat *st = (struct stat *) base; 14.30 + 14.31 + if (sizeof(struct stat) > size) 14.32 + return -L4_ENOMEM; 14.33 + 14.34 + return ::stat(path, st); 14.35 +} 14.36 + 14.37 /* Remove a filesystem object. */ 14.38 14.39 long HostFileOpener::remove_object(fileid_t fileid)
15.1 --- a/libfsserver/lib/files/opener_context_resource.cc Thu Feb 24 22:35:00 2022 +0100 15.2 +++ b/libfsserver/lib/files/opener_context_resource.cc Fri Feb 25 18:45:11 2022 +0100 15.3 @@ -1,7 +1,7 @@ 15.4 /* 15.5 * A context resource offering support for opening files. 15.6 * 15.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 15.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 15.9 * 15.10 * This program is free software; you can redistribute it and/or 15.11 * modify it under the terms of the GNU General Public License as 15.12 @@ -105,4 +105,14 @@ 15.13 return _opener->rename(source, target); 15.14 } 15.15 15.16 +long OpenerContextResource::stat() 15.17 +{ 15.18 + char *path = get_path(); 15.19 + 15.20 + if (path == NULL) 15.21 + return -L4_EINVAL; 15.22 + 15.23 + return _opener->stat(path, (void *) _region->start, _region->size()); 15.24 +} 15.25 + 15.26 // vim: tabstop=4 expandtab shiftwidth=4
16.1 --- a/libfsserver/lib/files/opener_resource.cc Thu Feb 24 22:35:00 2022 +0100 16.2 +++ b/libfsserver/lib/files/opener_resource.cc Fri Feb 25 18:45:11 2022 +0100 16.3 @@ -112,6 +112,13 @@ 16.4 return _registry->rename_provider(this, source, target); 16.5 } 16.6 16.7 +/* Obtain statistics metadata for the named filesystem object. */ 16.8 + 16.9 +long OpenerResource::stat(const char *path, void *base, offset_t size) 16.10 +{ 16.11 + return stat_object(path, base, size); 16.12 +} 16.13 + 16.14 16.15 16.16 /* Opener interface methods. */
17.1 --- a/libfsserver/lib/files/test_file_opener.cc Thu Feb 24 22:35:00 2022 +0100 17.2 +++ b/libfsserver/lib/files/test_file_opener.cc Fri Feb 25 18:45:11 2022 +0100 17.3 @@ -86,6 +86,14 @@ 17.4 return -L4_EIO; 17.5 } 17.6 17.7 +/* Populate a memory region with statistics metadata for a filesystem object. */ 17.8 + 17.9 +long TestFileOpener::stat_object(const char *path, void *base, offset_t size) 17.10 +{ 17.11 + (void) path; (void) base; (void) size; 17.12 + return -L4_EIO; 17.13 +} 17.14 + 17.15 /* Remove a filesystem object. */ 17.16 17.17 long TestFileOpener::remove_object(fileid_t fileid)
18.1 --- a/libsystypes/idl/file.idl Thu Feb 24 22:35:00 2022 +0100 18.2 +++ b/libsystypes/idl/file.idl Fri Feb 25 18:45:11 2022 +0100 18.3 @@ -5,10 +5,6 @@ 18.4 18.5 interface File 18.6 { 18.7 - /* Obtain a file metadata object. */ 18.8 - 18.9 - [opcode(11)] void fstat(out offset_t size, out cap statcap); 18.10 - 18.11 /* Resize the file. */ 18.12 18.13 [opcode(21)] void resize(inout offset_t size);
19.1 --- a/libsystypes/idl/opener_context.idl Thu Feb 24 22:35:00 2022 +0100 19.2 +++ b/libsystypes/idl/opener_context.idl Fri Feb 25 18:45:11 2022 +0100 19.3 @@ -28,6 +28,11 @@ 19.4 dataspace. */ 19.5 19.6 [opcode(15)] void rename(); 19.7 + 19.8 + /* Obtain file metadata given a path written to the context's dataspace, 19.9 + writing the metadata to the dataspace. */ 19.10 + 19.11 + [opcode(11)] void stat(); 19.12 }; 19.13 19.14 /* vim: tabstop=2 expandtab shiftwidth=2
20.1 --- a/tests/dstest_file_readdir.cc Thu Feb 24 22:35:00 2022 +0100 20.2 +++ b/tests/dstest_file_readdir.cc Fri Feb 25 18:45:11 2022 +0100 20.3 @@ -25,6 +25,7 @@ 20.4 #include <stdio.h> 20.5 #include <string.h> 20.6 #include <stdlib.h> 20.7 +#include <sys/sysmacros.h> /* major, minor */ 20.8 20.9 #include <fsclient/client.h> 20.10 #include <systypes/fcntl.h> 20.11 @@ -57,7 +58,44 @@ 20.12 20.13 while ((dirent = client_readdir(reader)) != NULL) 20.14 { 20.15 + char path[strlen(filename) + 1 + strlen(dirent->d_name) + 1]; 20.16 + struct stat st; 20.17 + 20.18 printf("> %s\n", dirent->d_name); 20.19 + 20.20 + /* Obtain file metadata. */ 20.21 + 20.22 + sprintf(path, "%s/%s", filename, dirent->d_name); 20.23 + 20.24 + if (client_stat(path, &st)) 20.25 + { 20.26 + printf("Could not obtain metadata for file: %s\n", dirent->d_name); 20.27 + return 1; 20.28 + } 20.29 + 20.30 + /* NOTE: From e2access... */ 20.31 + 20.32 + /* Terse stat output: 20.33 + %n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o %C */ 20.34 + 20.35 + printf("%s %ld %ld %x %d %d ", 20.36 + path, st.st_size, st.st_blocks, st.st_mode, st.st_uid, st.st_gid); 20.37 + 20.38 + printf("%d %d %d %x %x ", 20.39 + st.st_dev, st.st_ino, st.st_nlink, 20.40 + major(st.st_rdev), minor(st.st_rdev)); 20.41 + 20.42 + printf("%d %d %d ", 20.43 + st.st_atim, st.st_mtim, st.st_ctim); 20.44 + 20.45 + /* NOTE: Arbitrary values: 20.46 + %W (creation time) given as 0 20.47 + %o (I/O transfer size hint) given as 0 20.48 + %C (SELinux security context) given as empty string */ 20.49 + 20.50 + printf("%d %d %s\n", 20.51 + 0, 0, ""); 20.52 + 20.53 free(dirent); 20.54 } 20.55