1.1 --- a/conf/dstest_file_rename.cfg Wed Mar 02 23:23:37 2022 +0100 1.2 +++ b/conf/dstest_file_rename.cfg Wed Mar 02 23:53:42 2022 +0100 1.3 @@ -48,4 +48,4 @@ 1.4 log = { "client", "g" }, 1.5 }, 1.6 -- program, directory to read 1.7 - "rom/dstest_file_rename", "home/paulb/many"); 1.8 + "rom/dstest_file_rename", "home/paulb/many", "home/paulb/new");
2.1 --- a/libfsclient/include/fsclient/client.h Wed Mar 02 23:23:37 2022 +0100 2.2 +++ b/libfsclient/include/fsclient/client.h Wed Mar 02 23:53:42 2022 +0100 2.3 @@ -49,6 +49,9 @@ 2.4 2.5 /* Other file operations. */ 2.6 2.7 +long client_mkdir(const char *path, mode_t mode); 2.8 +long client_mkdir_using(const char *path, mode_t mode, l4_cap_idx_t server); 2.9 + 2.10 long client_remove(const char *path); 2.11 long client_remove_using(const char *path, l4_cap_idx_t server); 2.12
3.1 --- a/libfsclient/include/fsclient/file.h Wed Mar 02 23:23:37 2022 +0100 3.2 +++ b/libfsclient/include/fsclient/file.h Wed Mar 02 23:53:42 2022 +0100 3.3 @@ -85,6 +85,7 @@ 3.4 /* File operations. */ 3.5 3.6 void file_close(file_t *file); 3.7 +long file_mkdir(const char *filename, mode_t mode, l4_cap_idx_t server); 3.8 long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server); 3.9 long file_remove(const char *filename, l4_cap_idx_t server); 3.10 long file_rename(const char *source, const char *target, l4_cap_idx_t server); 3.11 @@ -93,6 +94,7 @@ 3.12 /* File lifecycle operations. */ 3.13 3.14 long file_context(file_t *file, l4_cap_idx_t server); 3.15 +long file_context_mkdir(mode_t mode, file_t *context); 3.16 long file_context_open(file_t *file, flags_t flags, file_t *context); 3.17 long file_context_remove(file_t *context); 3.18 long file_context_rename(file_t *context);
4.1 --- a/libfsclient/lib/src/client.cc Wed Mar 02 23:23:37 2022 +0100 4.2 +++ b/libfsclient/lib/src/client.cc Wed Mar 02 23:53:42 2022 +0100 4.3 @@ -359,6 +359,24 @@ 4.4 4.5 4.6 4.7 +/* Make a directory in the filesystem. */ 4.8 + 4.9 +long client_mkdir(const char *path, mode_t mode) 4.10 +{ 4.11 + l4_cap_idx_t server = l4re_env_get_cap("server"); 4.12 + 4.13 + return client_mkdir_using(path, mode, server); 4.14 +} 4.15 + 4.16 +/* Make a directory in the filesystem via a named capability. */ 4.17 + 4.18 +long client_mkdir_using(const char *path, mode_t mode, l4_cap_idx_t server) 4.19 +{ 4.20 + return file_mkdir(path, mode, server); 4.21 +} 4.22 + 4.23 + 4.24 + 4.25 /* Remove a file from the filesystem. */ 4.26 4.27 long client_remove(const char *path)
5.1 --- a/libfsclient/lib/src/file.cc Wed Mar 02 23:23:37 2022 +0100 5.2 +++ b/libfsclient/lib/src/file.cc Wed Mar 02 23:53:42 2022 +0100 5.3 @@ -113,6 +113,30 @@ 5.4 file_init(file); 5.5 } 5.6 5.7 +/* Make a directory in the filesystem. This is a convenience function invoking 5.8 + file_context and file_context_mkdir. */ 5.9 + 5.10 +long file_mkdir(const char *filename, mode_t mode, l4_cap_idx_t server) 5.11 +{ 5.12 + file_t context; 5.13 + long err; 5.14 + 5.15 + err = file_context(&context, server); 5.16 + if (err) 5.17 + return err; 5.18 + 5.19 + if (!file_string_set(&context, filename, 0, NULL)) 5.20 + return -L4_ENOMEM; 5.21 + 5.22 + err = file_context_mkdir(systypes_to_sys_mode(mode), &context); 5.23 + 5.24 + /* Close the context, although a separate mechanism could permit contexts to 5.25 + remove several files. */ 5.26 + 5.27 + file_close(&context); 5.28 + return err; 5.29 +} 5.30 + 5.31 /* Open a file using the given structure, indicating the filename and 5.32 filesystem server. The file_mmap function should be used to obtain access to 5.33 memory providing file data. This is a convenience function invoking 5.34 @@ -249,6 +273,14 @@ 5.35 return ipc_attach_dataspace(file->ref, size, (void **) &file->memory); 5.36 } 5.37 5.38 +/* Make a directory using the given context. */ 5.39 + 5.40 +long file_context_mkdir(mode_t mode, file_t *context) 5.41 +{ 5.42 + client_OpenerContext openercontext(context->ref); 5.43 + return openercontext.mkdir(mode); 5.44 +} 5.45 + 5.46 /* Open a file using the given structure and context. */ 5.47 5.48 long file_context_open(file_t *file, flags_t flags, file_t *context)
6.1 --- a/libfsserver/include/fsserver/ext2_file_opener.h Wed Mar 02 23:23:37 2022 +0100 6.2 +++ b/libfsserver/include/fsserver/ext2_file_opener.h Wed Mar 02 23:53:42 2022 +0100 6.3 @@ -66,6 +66,8 @@ 6.4 6.5 /* Filesystem object access and manipulation methods. */ 6.6 6.7 + virtual long make_directory_object(const char *path, sys_mode_t mode); 6.8 + 6.9 virtual long remove_object(fileid_t fileid); 6.10 6.11 virtual long rename_object(const char *source, const char *target);
7.1 --- a/libfsserver/include/fsserver/ext2_file_operations.h Wed Mar 02 23:23:37 2022 +0100 7.2 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Wed Mar 02 23:53:42 2022 +0100 7.3 @@ -78,6 +78,9 @@ 7.4 7.5 long find_file(const char *path, ext2_ino_t *ino, const char **remaining); 7.6 7.7 + long mkdir(ext2_ino_t ino_parent, const char *basename, sys_mode_t mode, 7.8 + user_t user); 7.9 + 7.10 long open_file(ext2_ino_t ino, ext2_file_t *file); 7.11 7.12 long remove(ext2_ino_t ino);
8.1 --- a/libfsserver/include/fsserver/file_opening.h Wed Mar 02 23:23:37 2022 +0100 8.2 +++ b/libfsserver/include/fsserver/file_opening.h Wed Mar 02 23:53:42 2022 +0100 8.3 @@ -49,6 +49,8 @@ 8.4 8.5 /* Filesystem object access and manipulation methods. */ 8.6 8.7 + virtual long make_directory_object(const char *path, sys_mode_t mode) = 0; 8.8 + 8.9 virtual long stat_object(const char *path, void *base, offset_t size) = 0; 8.10 8.11 virtual long remove_object(fileid_t fileid) = 0;
9.1 --- a/libfsserver/include/fsserver/host_file_opener.h Wed Mar 02 23:23:37 2022 +0100 9.2 +++ b/libfsserver/include/fsserver/host_file_opener.h Wed Mar 02 23:53:42 2022 +0100 9.3 @@ -80,6 +80,8 @@ 9.4 9.5 /* Filesystem object access and manipulation methods. */ 9.6 9.7 + virtual long make_directory_object(const char *path, sys_mode_t mode); 9.8 + 9.9 virtual long remove_object(fileid_t fileid); 9.10 9.11 virtual long rename_object(const char *source, const char *target);
10.1 --- a/libfsserver/include/fsserver/opener_context_resource.h Wed Mar 02 23:23:37 2022 +0100 10.2 +++ b/libfsserver/include/fsserver/opener_context_resource.h Wed Mar 02 23:53:42 2022 +0100 10.3 @@ -57,6 +57,8 @@ 10.4 10.5 /* Opener context interface methods. */ 10.6 10.7 + long mkdir(sys_mode_t mode); 10.8 + 10.9 long open(flags_t flags, offset_t *size, l4_cap_idx_t *file, 10.10 object_flags_t *object_flags); 10.11
11.1 --- a/libfsserver/include/fsserver/opener_resource.h Wed Mar 02 23:23:37 2022 +0100 11.2 +++ b/libfsserver/include/fsserver/opener_resource.h Wed Mar 02 23:53:42 2022 +0100 11.3 @@ -56,6 +56,8 @@ 11.4 11.5 /* Direct access methods. */ 11.6 11.7 + long mkdir(const char *path, sys_mode_t mode); 11.8 + 11.9 long open(const char *path, flags_t flags, offset_t *size, 11.10 l4_cap_idx_t *cap, object_flags_t *object_flags); 11.11
12.1 --- a/libfsserver/include/fsserver/test_file_opener.h Wed Mar 02 23:23:37 2022 +0100 12.2 +++ b/libfsserver/include/fsserver/test_file_opener.h Wed Mar 02 23:53:42 2022 +0100 12.3 @@ -57,6 +57,8 @@ 12.4 12.5 /* Filesystem object access and manipulation methods. */ 12.6 12.7 + virtual long make_directory_object(const char *path, sys_mode_t mode); 12.8 + 12.9 virtual long remove_object(fileid_t fileid); 12.10 12.11 virtual long rename_object(const char *source, const char *target);
13.1 --- a/libfsserver/lib/files/ext2_file_opener.cc Wed Mar 02 23:23:37 2022 +0100 13.2 +++ b/libfsserver/lib/files/ext2_file_opener.cc Wed Mar 02 23:53:42 2022 +0100 13.3 @@ -132,6 +132,34 @@ 13.4 13.5 13.6 13.7 +/* Make a new directory. */ 13.8 + 13.9 +long Ext2FileOpener::make_directory_object(const char *path, sys_mode_t mode) 13.10 +{ 13.11 + fileid_t fileid, parent; 13.12 + long err; 13.13 + 13.14 + /* Test for an existing object. */ 13.15 + 13.16 + err = get_fileid(path, 0, &fileid); 13.17 + 13.18 + if (!err) 13.19 + return -L4_EEXIST; 13.20 + 13.21 + if (err != -L4_ENOENT) 13.22 + return err; 13.23 + 13.24 + /* Obtain the parent of the new directory. */ 13.25 + 13.26 + err = get_parent(path, &parent); 13.27 + 13.28 + if (err) 13.29 + return err; 13.30 + 13.31 + return _ops->mkdir((ext2_ino_t) parent, path_basename(path), 13.32 + systypes_from_sys_mode(mode), _user); 13.33 +} 13.34 + 13.35 /* Remove a filesystem object. */ 13.36 13.37 long Ext2FileOpener::remove_object(fileid_t fileid)
14.1 --- a/libfsserver/lib/files/ext2_file_operations.cc Wed Mar 02 23:23:37 2022 +0100 14.2 +++ b/libfsserver/lib/files/ext2_file_operations.cc Wed Mar 02 23:53:42 2022 +0100 14.3 @@ -129,6 +129,34 @@ 14.4 return L4_EOK; 14.5 } 14.6 14.7 +/* Make a new directory. */ 14.8 + 14.9 +long Ext2FileOperations::mkdir(ext2_ino_t ino_parent, const char *basename, 14.10 + sys_mode_t mode, user_t user) 14.11 +{ 14.12 + std::lock_guard<std::mutex> guard(_lock); 14.13 + 14.14 + ext2_ino_t ino; 14.15 + errcode_t retval; 14.16 + 14.17 + /* Test for permission to create the directory. */ 14.18 + 14.19 + if (!can_access(user, O_WRONLY, ino_parent)) 14.20 + return -L4_EPERM; 14.21 + 14.22 + /* Make the directory. */ 14.23 + 14.24 + retval = image_make_dir(_fs, ino_parent, basename, mode, user.uid, user.gid, 14.25 + &ino); 14.26 + 14.27 + // NOTE: Map error conditions. 14.28 + 14.29 + if (retval) 14.30 + return -L4_EIO; 14.31 + 14.32 + return L4_EOK; 14.33 +} 14.34 + 14.35 /* Open the file associated with the indicated inode. */ 14.36 14.37 long Ext2FileOperations::open_file(ext2_ino_t ino, ext2_file_t *file)
15.1 --- a/libfsserver/lib/files/host_file_opener.cc Wed Mar 02 23:23:37 2022 +0100 15.2 +++ b/libfsserver/lib/files/host_file_opener.cc Wed Mar 02 23:53:42 2022 +0100 15.3 @@ -198,6 +198,31 @@ 15.4 15.5 15.6 15.7 +/* Make a new directory. */ 15.8 + 15.9 +long HostFileOpener::make_directory_object(const char *path, sys_mode_t mode) 15.10 +{ 15.11 + int err = mkdir(path, systypes_from_sys_mode(mode)); 15.12 + 15.13 + // NOTE: Other return codes may need converting. 15.14 + 15.15 + switch (err) 15.16 + { 15.17 + case 0: break; 15.18 + case EACCES: return -L4_EPERM; 15.19 + case EEXIST: return -L4_EEXIST; 15.20 + case ENOENT: return -L4_ENOENT; 15.21 + default: return -L4_EIO; 15.22 + } 15.23 + 15.24 + fileid_t fileid = _get_fileid(path, true); 15.25 + 15.26 + _fileids[path] = fileid; 15.27 + _paths[fileid] = path; 15.28 + 15.29 + return L4_EOK; 15.30 +} 15.31 + 15.32 /* Remove a filesystem object. */ 15.33 15.34 long HostFileOpener::remove_object(fileid_t fileid)
16.1 --- a/libfsserver/lib/files/opener_context_resource.cc Wed Mar 02 23:23:37 2022 +0100 16.2 +++ b/libfsserver/lib/files/opener_context_resource.cc Wed Mar 02 23:53:42 2022 +0100 16.3 @@ -67,6 +67,16 @@ 16.4 16.5 /* Opener context interface methods. */ 16.6 16.7 +long OpenerContextResource::mkdir(sys_mode_t mode) 16.8 +{ 16.9 + char *path = get_path(); 16.10 + 16.11 + if (path == NULL) 16.12 + return -L4_EINVAL; 16.13 + 16.14 + return _opener->mkdir(path, mode); 16.15 +} 16.16 + 16.17 long OpenerContextResource::open(flags_t flags, offset_t *size, 16.18 l4_cap_idx_t *file, object_flags_t *object_flags) 16.19 {
17.1 --- a/libfsserver/lib/files/opener_resource.cc Wed Mar 02 23:23:37 2022 +0100 17.2 +++ b/libfsserver/lib/files/opener_resource.cc Wed Mar 02 23:53:42 2022 +0100 17.3 @@ -78,6 +78,13 @@ 17.4 17.5 17.6 17.7 +/* Make a directory. */ 17.8 + 17.9 +long OpenerResource::mkdir(const char *path, sys_mode_t mode) 17.10 +{ 17.11 + return make_directory_object(path, mode); 17.12 +} 17.13 + 17.14 /* Return an object for the given path and flags. */ 17.15 17.16 long OpenerResource::open(const char *path, flags_t flags, offset_t *size,
18.1 --- a/libfsserver/lib/files/test_file_opener.cc Wed Mar 02 23:23:37 2022 +0100 18.2 +++ b/libfsserver/lib/files/test_file_opener.cc Wed Mar 02 23:53:42 2022 +0100 18.3 @@ -88,6 +88,14 @@ 18.4 18.5 18.6 18.7 +/* Make a new directory. */ 18.8 + 18.9 +long TestFileOpener::make_directory_object(const char *path, sys_mode_t mode) 18.10 +{ 18.11 + (void) path; (void) mode; 18.12 + return -L4_EIO; 18.13 +} 18.14 + 18.15 /* Remove a filesystem object. */ 18.16 18.17 long TestFileOpener::remove_object(fileid_t fileid)
19.1 --- a/libsystypes/idl/opener_context.idl Wed Mar 02 23:23:37 2022 +0100 19.2 +++ b/libsystypes/idl/opener_context.idl Wed Mar 02 23:53:42 2022 +0100 19.3 @@ -15,6 +15,10 @@ 19.4 19.5 [opcode(1)] void getfs(out cap fs); 19.6 19.7 + /* Make a new directory given a path written to the context's dataspace. */ 19.8 + 19.9 + [opcode(18)] void mkdir(in sys_mode_t mode); 19.10 + 19.11 /* Obtain a file reference given a path written to the context's dataspace. */ 19.12 19.13 [opcode(12)] void open(in flags_t flags, out offset_t size, out cap file,
20.1 --- a/libsystypes/include/systypes/base.h Wed Mar 02 23:23:37 2022 +0100 20.2 +++ b/libsystypes/include/systypes/base.h Wed Mar 02 23:53:42 2022 +0100 20.3 @@ -81,6 +81,14 @@ 20.4 typedef long sys_blksize_t; /* input/output block size */ 20.5 typedef long sys_blkcnt_t; /* number of 512-byte blocks */ 20.6 20.7 +/* Conversions. */ 20.8 + 20.9 +#define systypes_from_sys_mode(mode) \ 20.10 +((mode_t) mode) 20.11 + 20.12 +#define systypes_to_sys_mode(mode) \ 20.13 +((sys_mode_t) mode) 20.14 + 20.15 /* Factory types for L4 factory interface invocations. */ 20.16 20.17 ipc_varg_typedef(sys_mode_t, ipc_varg_sys_mode_t)
21.1 --- a/tests/dstest_file_rename.cc Wed Mar 02 23:23:37 2022 +0100 21.2 +++ b/tests/dstest_file_rename.cc Wed Mar 02 23:53:42 2022 +0100 21.3 @@ -31,15 +31,52 @@ 21.4 21.5 21.6 21.7 -int main(int argc, char *argv[]) 21.8 +/* Show a directory's contents and determine if all expected files are 21.9 + present. */ 21.10 + 21.11 +static int show_directory(const char *filename, int expected) 21.12 { 21.13 - if (argc < 2) 21.14 + file_t *reader = client_opendir(filename); 21.15 + 21.16 + if (reader == NULL) 21.17 { 21.18 - printf("Need a directory name.\n"); 21.19 + printf("Could not read from directory.\n"); 21.20 return 1; 21.21 } 21.22 21.23 - char *filename = argv[1]; 21.24 + printf("Reading...\n"); 21.25 + 21.26 + struct dirent *dirent; 21.27 + int renamed = 0; 21.28 + 21.29 + while ((dirent = client_readdir(reader)) != NULL) 21.30 + { 21.31 + if (!strncmp(dirent->d_name, "renamed-", 8)) 21.32 + renamed++; 21.33 + 21.34 + printf("> %s\n", dirent->d_name); 21.35 + free(dirent); 21.36 + } 21.37 + 21.38 + printf("Directory shown.\n"); 21.39 + 21.40 + printf("Renamed files: %d (%d)\n", renamed, expected); 21.41 + 21.42 + if (renamed != expected) 21.43 + return 1; 21.44 + 21.45 + return 0; 21.46 +} 21.47 + 21.48 +int main(int argc, char *argv[]) 21.49 +{ 21.50 + if (argc < 3) 21.51 + { 21.52 + printf("Need a directory containing files and a new directory name.\n"); 21.53 + return 1; 21.54 + } 21.55 + 21.56 + char *filename = argv[1], *newdir = argv[2]; 21.57 21.58 printf("Opening %s...\n", filename); 21.59 21.60 @@ -68,13 +105,14 @@ 21.61 char source[strlen(filename) + strlen("/file-XXXX.txt") + 10]; 21.62 char target[strlen(filename) + strlen("/file-XXXX.txt") + 10]; 21.63 int filenum, to_rename = 100; 21.64 + long err; 21.65 21.66 for (filenum = 1; filenum <= to_rename; filenum++) 21.67 { 21.68 sprintf(source, "%s/file-%d.txt", filename, filenum); 21.69 sprintf(target, "%s/renamed-%d.txt", filename, filenum); 21.70 21.71 - long err = client_rename(source, target); 21.72 + err = client_rename(source, target); 21.73 21.74 if (err) 21.75 { 21.76 @@ -85,6 +123,19 @@ 21.77 21.78 /* Show the new listing. */ 21.79 21.80 + if (show_directory(filename, to_rename)) 21.81 + return 1; 21.82 + 21.83 + /* Create a directory and move files into it. */ 21.84 + 21.85 + err = client_mkdir(newdir, 0755); 21.86 + 21.87 + if (err) 21.88 + { 21.89 + printf("Could not make directory: %s\n", newdir); 21.90 + return 1; 21.91 + } 21.92 + 21.93 reader = client_opendir(filename); 21.94 21.95 if (reader == NULL) 21.96 @@ -93,22 +144,33 @@ 21.97 return 1; 21.98 } 21.99 21.100 - printf("Reading...\n"); 21.101 - 21.102 - int renamed = 0; 21.103 + printf("Renaming...\n"); 21.104 21.105 while ((dirent = client_readdir(reader)) != NULL) 21.106 { 21.107 if (!strncmp(dirent->d_name, "renamed-", 8)) 21.108 - renamed++; 21.109 + { 21.110 + sprintf(source, "%s/%s", filename, dirent->d_name); 21.111 + sprintf(target, "%s/%s", newdir, dirent->d_name); 21.112 + 21.113 + err = client_rename(source, target); 21.114 21.115 - printf("> %s\n", dirent->d_name); 21.116 + if (err) 21.117 + { 21.118 + printf("Could not rename file: %s\n", source); 21.119 + return 1; 21.120 + } 21.121 + } 21.122 + 21.123 free(dirent); 21.124 } 21.125 21.126 - printf("Directory shown.\n"); 21.127 + /* Show the new directory's listing. */ 21.128 21.129 - printf("Renamed files: %d (%d)\n", renamed, to_rename); 21.130 + if (show_directory(newdir, to_rename)) 21.131 + return 1; 21.132 + 21.133 + printf("End of tests.\n"); 21.134 21.135 return 0; 21.136 }