1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/conf/dstest_file_rename.cfg Thu Jan 27 23:45:17 2022 +0100 1.3 @@ -0,0 +1,51 @@ 1.4 +-- vim:set ft=lua: 1.5 + 1.6 +local L4 = require("L4"); 1.7 + 1.8 +local l = L4.default_loader; 1.9 + 1.10 +local pipe_server = l:new_channel(); 1.11 + 1.12 +l:startv({ 1.13 + caps = { 1.14 + server = pipe_server:svr(), 1.15 + }, 1.16 + log = { "pipes", "r" }, 1.17 + }, 1.18 + "rom/dstest_pipe_server", "10"); 1.19 + 1.20 +local block_server = l:new_channel(); 1.21 + 1.22 +l:startv({ 1.23 + caps = { 1.24 + server = block_server:svr(), 1.25 + }, 1.26 + log = { "blocksvr", "r" }, 1.27 + }, 1.28 + "rom/dstest_block_server", "10"); 1.29 + 1.30 +local ext2svr = l:new_channel(); 1.31 + 1.32 +l:startv({ 1.33 + caps = { 1.34 + blocksvr = block_server, 1.35 + pipes = pipe_server, 1.36 + ext2svr = ext2svr:svr(), 1.37 + }, 1.38 + log = { "ext2svr", "y" }, 1.39 + }, 1.40 + "rom/dstest_ext2_server", "blocksvr", "rom/e2test.fs", "10", "ext2svr"); 1.41 + 1.42 +-- Obtain user filesystems with umask 0022 (18). 1.43 + 1.44 +local open_for_user = 6; 1.45 +local ext2svr_paulb = L4.cast(L4.Proto.Factory, ext2svr):create(open_for_user, 1000, 1000, 18); 1.46 + 1.47 +l:startv({ 1.48 + caps = { 1.49 + server = ext2svr_paulb, 1.50 + }, 1.51 + log = { "client", "g" }, 1.52 + }, 1.53 + -- program, directory to read 1.54 + "rom/dstest_file_rename", "home/paulb/many");
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/conf/dstest_file_rename.list Thu Jan 27 23:45:17 2022 +0100 2.3 @@ -0,0 +1,28 @@ 2.4 +entry dstest_file_rename 2.5 +roottask moe rom/dstest_file_rename.cfg 2.6 +module dstest_file_rename.cfg 2.7 +module e2test.fs 2.8 +module l4re 2.9 +module ned 2.10 +module dstest_file_rename 2.11 +module dstest_ext2_server 2.12 +module dstest_block_server 2.13 +module dstest_pipe_server 2.14 +module lib4re-c.so 2.15 +module lib4re-c-util.so 2.16 +module lib4re.so 2.17 +module lib4re-util.so 2.18 +module libc_be_l4refile.so 2.19 +module libc_be_l4re.so 2.20 +module libc_be_socket_noop.so 2.21 +module libc_support_misc.so 2.22 +module libdl.so 2.23 +module libipc.so 2.24 +module libl4sys-direct.so 2.25 +module libl4sys.so 2.26 +module libl4util.so 2.27 +module libld-l4.so 2.28 +module libpthread.so 2.29 +module libstdc++.so 2.30 +module libsupc++.so 2.31 +module libuc_c.so
3.1 --- a/libe2access/include/e2access/image.h Fri Jan 14 01:10:35 2022 +0100 3.2 +++ b/libe2access/include/e2access/image.h Thu Jan 27 23:45:17 2022 +0100 3.3 @@ -1,7 +1,7 @@ 3.4 /* 3.5 * Filesystem image access functions. 3.6 * 3.7 - * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk> 3.8 + * Copyright (C) 2019, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 3.9 * 3.10 * This program is free software; you can redistribute it and/or 3.11 * modify it under the terms of the GNU General Public License as 3.12 @@ -33,6 +33,8 @@ 3.13 const char *basename, __u16 mode, 3.14 __u16 uid, __u16 gid, ext2_ino_t *ino_file); 3.15 3.16 +int image_file_type(int mode); 3.17 + 3.18 errcode_t image_find_next(ext2_filsys fs, ext2_ino_t ino_dir, 3.19 const char **basename, char *buf, ext2_ino_t *ino); 3.20 3.21 @@ -64,6 +66,10 @@ 3.22 3.23 errcode_t image_remove_by_inode(ext2_filsys fs, ext2_ino_t ino); 3.24 3.25 +errcode_t image_rename(ext2_filsys fs, ext2_ino_t source, 3.26 + ext2_ino_t source_parent, const char *source_basename, 3.27 + ext2_ino_t target_parent, const char *target_basename); 3.28 + 3.29 void image_set_metadata(struct ext2_inode *inode, int clean, __u16 mode, 3.30 __u16 uid, __u16 gid); 3.31
4.1 --- a/libe2access/lib/src/image.c Fri Jan 14 01:10:35 2022 +0100 4.2 +++ b/libe2access/lib/src/image.c Thu Jan 27 23:45:17 2022 +0100 4.3 @@ -28,28 +28,20 @@ 4.4 4.5 4.6 4.7 -/* Create an inode for a file. */ 4.8 +/* Link an inode within the given target directory having the given basename. */ 4.9 4.10 -errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target, 4.11 - const char *basename, __u16 mode, 4.12 - __u16 uid, __u16 gid, ext2_ino_t *ino_file) 4.13 +static errcode_t _image_link(ext2_filsys fs, ext2_ino_t ino_target, 4.14 + const char *basename, ext2_ino_t ino_file, 4.15 + int flags) 4.16 { 4.17 - struct ext2_inode inode_file; 4.18 errcode_t retval; 4.19 int retry; 4.20 4.21 - /* Without an inode, create a new one. */ 4.22 - 4.23 - retval = ext2fs_new_inode(fs, ino_target, LINUX_S_IFREG | mode, 0, ino_file); 4.24 - if (retval) 4.25 - return retval; 4.26 - 4.27 /* Connect the inode to its parent. */ 4.28 4.29 for (retry = 0; retry <= 1; retry++) 4.30 { 4.31 - retval = ext2fs_link(fs, ino_target, basename, *ino_file, 4.32 - EXT2_FT_REG_FILE); 4.33 + retval = ext2fs_link(fs, ino_target, basename, ino_file, flags); 4.34 4.35 if (!retval) 4.36 break; 4.37 @@ -65,6 +57,50 @@ 4.38 return retval; 4.39 } 4.40 4.41 + return 0; 4.42 +} 4.43 + 4.44 +/* Update the parent entry of a renamed directory. */ 4.45 + 4.46 +struct _image_parent_entry_state 4.47 +{ 4.48 + ext2_ino_t ino; 4.49 +}; 4.50 + 4.51 +static int _image_update_parent_entry(struct ext2_dir_entry *dir_entry, 4.52 + int offset, int blocksize, char *buf, 4.53 + void *priv_data) 4.54 +{ 4.55 + struct _image_parent_entry_state *state = (struct _image_parent_entry_state *) priv_data; 4.56 + 4.57 + (void) offset; (void) blocksize; (void) buf; 4.58 + 4.59 + if (strcmp(dir_entry->name, "..") == 0) 4.60 + { 4.61 + dir_entry->inode = state->ino; 4.62 + return DIRENT_CHANGED | DIRENT_ABORT; 4.63 + } 4.64 + else 4.65 + return 0; 4.66 +} 4.67 + 4.68 +/* Create an inode for a file. */ 4.69 + 4.70 +errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target, 4.71 + const char *basename, __u16 mode, 4.72 + __u16 uid, __u16 gid, ext2_ino_t *ino_file) 4.73 +{ 4.74 + struct ext2_inode inode_file; 4.75 + errcode_t retval; 4.76 + 4.77 + /* Without an inode, create a new one. */ 4.78 + 4.79 + retval = ext2fs_new_inode(fs, ino_target, LINUX_S_IFREG | mode, 0, ino_file); 4.80 + if (retval) 4.81 + return retval; 4.82 + 4.83 + _image_link(fs, ino_target, basename, *ino_file, EXT2_FT_REG_FILE); 4.84 + 4.85 /* Make sure that subsequent files employ different inodes. */ 4.86 4.87 ext2fs_inode_alloc_stats2(fs, *ino_file, 1, 0); 4.88 @@ -77,6 +113,26 @@ 4.89 return ext2fs_write_new_inode(fs, *ino_file, &inode_file); 4.90 } 4.91 4.92 +/* Return the appropriate ext2 file type value for the given mode value. */ 4.93 + 4.94 +int image_file_type(int mode) 4.95 +{ 4.96 + switch (mode & LINUX_S_IFMT) 4.97 + { 4.98 + case LINUX_S_IFSOCK: return EXT2_FT_SOCK; 4.99 + case LINUX_S_IFLNK: return EXT2_FT_SYMLINK; 4.100 + case LINUX_S_IFREG: return EXT2_FT_REG_FILE; 4.101 + case LINUX_S_IFBLK: return EXT2_FT_BLKDEV; 4.102 + case LINUX_S_IFDIR: return EXT2_FT_DIR; 4.103 + case LINUX_S_IFCHR: return EXT2_FT_CHRDEV; 4.104 + case LINUX_S_IFIFO: return EXT2_FT_FIFO; 4.105 + 4.106 + /* NOTE: Perhaps signal an error. */ 4.107 + 4.108 + default: return EXT2_FT_REG_FILE; 4.109 + } 4.110 +} 4.111 + 4.112 /* Find an object in the given directory with the given name in the filesystem 4.113 image, updating the name reference to refer to the next component. */ 4.114 4.115 @@ -348,6 +404,83 @@ 4.116 sizeof(inode)); 4.117 } 4.118 4.119 +/* Rename a file. */ 4.120 + 4.121 +errcode_t image_rename(ext2_filsys fs, ext2_ino_t source, 4.122 + ext2_ino_t source_parent, const char *source_basename, 4.123 + ext2_ino_t target_parent, const char *target_basename) 4.124 +{ 4.125 + errcode_t retval; 4.126 + struct ext2_inode source_inode, source_parent_inode, target_parent_inode; 4.127 + struct _image_parent_entry_state state = {target_parent}; 4.128 + 4.129 + /* NOTE: Should check for space. */ 4.130 + 4.131 + /* Obtain the source object. */ 4.132 + 4.133 + retval = ext2fs_read_inode(fs, source, &source_inode); 4.134 + 4.135 + if (retval) 4.136 + return retval; 4.137 + 4.138 + /* Link from the target parent. */ 4.139 + 4.140 + retval = _image_link(fs, target_parent, target_basename, source, 4.141 + image_file_type(source_inode.i_mode)); 4.142 + 4.143 + if (retval) 4.144 + return retval; 4.145 + 4.146 + if (_image_isdir(fs, source)) 4.147 + { 4.148 + /* Update the link count for the target. */ 4.149 + 4.150 + retval = ext2fs_read_inode(fs, target_parent, &target_parent_inode); 4.151 + 4.152 + if (retval) 4.153 + return retval; 4.154 + 4.155 + target_parent_inode.i_links_count++; 4.156 + 4.157 + retval = ext2fs_write_inode(fs, target_parent, &target_parent_inode); 4.158 + 4.159 + if (retval) 4.160 + return retval; 4.161 + 4.162 + /* A directory needs its .. entry updating to refer to its new 4.163 + parent. */ 4.164 + 4.165 + retval = ext2fs_dir_iterate(fs, source, 0, NULL, 4.166 + _image_update_parent_entry, &state); 4.167 + 4.168 + /* Update the link count for the source. */ 4.169 + 4.170 + retval = ext2fs_read_inode(fs, source_parent, &source_parent_inode); 4.171 + 4.172 + if (retval) 4.173 + return retval; 4.174 + 4.175 + source_parent_inode.i_links_count--; 4.176 + 4.177 + retval = ext2fs_write_inode(fs, source_parent, &source_parent_inode); 4.178 + 4.179 + if (retval) 4.180 + return retval; 4.181 + } 4.182 + 4.183 + /* Unlink from the source parent, doing so by name because the file is now 4.184 + already linked from the target parent, and when the parents are the same, 4.185 + unlinking by inode could just cause the file to disappear from the 4.186 + catalogue. */ 4.187 + 4.188 + retval = image_unlink_by_name(fs, source_parent, source_basename); 4.189 + 4.190 + if (retval) 4.191 + return retval; 4.192 + 4.193 + return ext2fs_flush2(fs, 0); 4.194 +} 4.195 + 4.196 /* Set the mode, user and group metadata for a file. */ 4.197 4.198 void image_set_metadata(struct ext2_inode *inode, int clean, __u16 mode, 4.199 @@ -396,6 +529,8 @@ 4.200 errcode_t image_unlink_by_name(ext2_filsys fs, ext2_ino_t ino_parent, 4.201 const char *basename) 4.202 { 4.203 + /* NOTE: This might do more work for a directory. */ 4.204 + 4.205 return ext2fs_unlink(fs, ino_parent, basename, 0, 0); 4.206 } 4.207 4.208 @@ -404,6 +539,8 @@ 4.209 errcode_t image_unlink_by_inode(ext2_filsys fs, ext2_ino_t ino_parent, 4.210 ext2_ino_t ino) 4.211 { 4.212 + /* NOTE: This might do more work for a directory. */ 4.213 + 4.214 return ext2fs_unlink(fs, ino_parent, 0, ino, 0); 4.215 } 4.216 4.217 @@ -448,3 +585,6 @@ 4.218 4.219 return _image_isfile(fs, ino); 4.220 } 4.221 + 4.222 +/* vim: tabstop=4 expandtab shiftwidth=4 4.223 +*/
5.1 --- a/libfsclient/include/fsclient/client.h Fri Jan 14 01:10:35 2022 +0100 5.2 +++ b/libfsclient/include/fsclient/client.h Thu Jan 27 23:45:17 2022 +0100 5.3 @@ -1,7 +1,7 @@ 5.4 /* 5.5 * Filesystem client functions. 5.6 * 5.7 - * Copyright (C) 2018, 2019, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 5.8 + * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 5.9 * 5.10 * This program is free software; you can redistribute it and/or 5.11 * modify it under the terms of the GNU General Public License as 5.12 @@ -52,6 +52,9 @@ 5.13 long client_remove(const char *name); 5.14 long client_remove_using(const char *name, l4_cap_idx_t server); 5.15 5.16 +long client_rename(const char *source, const char *target); 5.17 +long client_rename_using(const char *source, const char *target, l4_cap_idx_t server); 5.18 + 5.19 /* File and region operations. */ 5.20 5.21 long client_flush(file_t *file);
6.1 --- a/libfsclient/include/fsclient/file.h Fri Jan 14 01:10:35 2022 +0100 6.2 +++ b/libfsclient/include/fsclient/file.h Thu Jan 27 23:45:17 2022 +0100 6.3 @@ -1,7 +1,7 @@ 6.4 /* 6.5 * File access convenience functions and types. 6.6 * 6.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 6.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 6.9 * 6.10 * This program is free software; you can redistribute it and/or 6.11 * modify it under the terms of the GNU General Public License as 6.12 @@ -85,12 +85,14 @@ 6.13 void file_close(file_t *file); 6.14 long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server); 6.15 long file_remove(const char *filename, l4_cap_idx_t server); 6.16 +long file_rename(const char *source, const char *target, l4_cap_idx_t server); 6.17 6.18 /* File lifecycle operations. */ 6.19 6.20 long file_context(file_t *file, l4_cap_idx_t server); 6.21 long file_context_open(file_t *file, flags_t flags, file_t *context); 6.22 long file_context_remove(file_t *context); 6.23 +long file_context_rename(file_t *context); 6.24 void file_init(file_t *file); 6.25 6.26 /* File and region operations. */
7.1 --- a/libfsclient/lib/src/client.cc Fri Jan 14 01:10:35 2022 +0100 7.2 +++ b/libfsclient/lib/src/client.cc Thu Jan 27 23:45:17 2022 +0100 7.3 @@ -1,7 +1,7 @@ 7.4 /* 7.5 * Filesystem client functions. 7.6 * 7.7 - * Copyright (C) 2018, 2019, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 7.8 + * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 7.9 * 7.10 * This program is free software; you can redistribute it and/or 7.11 * modify it under the terms of the GNU General Public License as 7.12 @@ -377,6 +377,24 @@ 7.13 7.14 7.15 7.16 +/* Rename a file in the filesystem. */ 7.17 + 7.18 +long client_rename(const char *source, const char *target) 7.19 +{ 7.20 + l4_cap_idx_t server = l4re_env_get_cap("server"); 7.21 + 7.22 + return client_rename_using(source, target, server); 7.23 +} 7.24 + 7.25 +/* Rename a file in the filesystem via a named capability. */ 7.26 + 7.27 +long client_rename_using(const char *source, const char *target, l4_cap_idx_t server) 7.28 +{ 7.29 + return file_rename(source, target, server); 7.30 +} 7.31 + 7.32 + 7.33 + 7.34 /* Obtain the current region of a pipe. */ 7.35 7.36 long client_current_region(file_t *file)
8.1 --- a/libfsclient/lib/src/file.cc Fri Jan 14 01:10:35 2022 +0100 8.2 +++ b/libfsclient/lib/src/file.cc Thu Jan 27 23:45:17 2022 +0100 8.3 @@ -1,7 +1,7 @@ 8.4 /* 8.5 * File access convenience functions. 8.6 * 8.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 8.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 8.9 * 8.10 * This program is free software; you can redistribute it and/or 8.11 * modify it under the terms of the GNU General Public License as 8.12 @@ -155,7 +155,35 @@ 8.13 err = file_context_remove(&context); 8.14 8.15 /* Close the context, although a separate mechanism could permit contexts to 8.16 - open several files. */ 8.17 + remove several files. */ 8.18 + 8.19 + file_close(&context); 8.20 + return err; 8.21 +} 8.22 + 8.23 +/* Rename an object in the filesystem. This is a convenience function invoking 8.24 + file_context and file_context_rename. */ 8.25 + 8.26 +long file_rename(const char *source, const char *target, l4_cap_idx_t server) 8.27 +{ 8.28 + file_t context; 8.29 + offset_t written; 8.30 + long err; 8.31 + 8.32 + err = file_context(&context, server); 8.33 + if (err) 8.34 + return err; 8.35 + 8.36 + if (!file_string_set(&context, source, 0, &written)) 8.37 + return -L4_ENOMEM; 8.38 + 8.39 + if (!file_string_set(&context, target, written + 1, NULL)) 8.40 + return -L4_ENOMEM; 8.41 + 8.42 + err = file_context_rename(&context); 8.43 + 8.44 + /* Close the context, although a separate mechanism could permit contexts to 8.45 + rename several files. */ 8.46 8.47 file_close(&context); 8.48 return err; 8.49 @@ -211,6 +239,14 @@ 8.50 return openercontext.remove(); 8.51 } 8.52 8.53 +/* Rename a file using the given context. */ 8.54 + 8.55 +long file_context_rename(file_t *context) 8.56 +{ 8.57 + client_OpenerContext openercontext(context->ref); 8.58 + return openercontext.rename(); 8.59 +} 8.60 + 8.61 8.62 8.63 /* Flush populated data and obtain an updated file size and populated data
9.1 --- a/libfsserver/include/fsserver/ext2_file_opener.h Fri Jan 14 01:10:35 2022 +0100 9.2 +++ b/libfsserver/include/fsserver/ext2_file_opener.h Thu Jan 27 23:45:17 2022 +0100 9.3 @@ -1,7 +1,7 @@ 9.4 /* 9.5 * An opener for a file provided by an Ext2-compatible filesystem. 9.6 * 9.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 9.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 9.9 * 9.10 * This program is free software; you can redistribute it and/or 9.11 * modify it under the terms of the GNU General Public License as 9.12 @@ -65,6 +65,9 @@ 9.13 9.14 virtual long remove_object(const char *path, fileid_t fileid); 9.15 9.16 + virtual long rename_object(const char *source, fileid_t source_fileid, 9.17 + const char *target); 9.18 + 9.19 virtual long unlink_object(const char *path, fileid_t fileid); 9.20 }; 9.21
10.1 --- a/libfsserver/include/fsserver/ext2_file_operations.h Fri Jan 14 01:10:35 2022 +0100 10.2 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Thu Jan 27 23:45:17 2022 +0100 10.3 @@ -1,7 +1,7 @@ 10.4 /* 10.5 * File operations supporting an Ext2-compatible filesystem. 10.6 * 10.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 10.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 10.9 * 10.10 * This program is free software; you can redistribute it and/or 10.11 * modify it under the terms of the GNU General Public License as 10.12 @@ -72,6 +72,10 @@ 10.13 10.14 long remove(ext2_ino_t ino); 10.15 10.16 + long rename(ext2_ino_t source, 10.17 + ext2_ino_t source_parent, const char *source_basename, 10.18 + ext2_ino_t target_parent, const char *target_basename); 10.19 + 10.20 long unlink(ext2_ino_t ino_parent, ext2_ino_t ino); 10.21 10.22 /* File property methods. */
11.1 --- a/libfsserver/include/fsserver/file_opening.h Fri Jan 14 01:10:35 2022 +0100 11.2 +++ b/libfsserver/include/fsserver/file_opening.h Thu Jan 27 23:45:17 2022 +0100 11.3 @@ -1,7 +1,7 @@ 11.4 /* 11.5 * Generic support for opening files. 11.6 * 11.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 11.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 11.9 * 11.10 * This program is free software; you can redistribute it and/or 11.11 * modify it under the terms of the GNU General Public License as 11.12 @@ -37,6 +37,8 @@ 11.13 11.14 virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid) = 0; 11.15 11.16 + virtual long get_parent(const char *path, fileid_t *fileid); 11.17 + 11.18 virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, 11.19 Accessor **accessor) = 0; 11.20 11.21 @@ -46,6 +48,9 @@ 11.22 11.23 virtual long remove_object(const char *path, fileid_t fileid) = 0; 11.24 11.25 + virtual long rename_object(const char *source, fileid_t source_fileid, 11.26 + const char *target) = 0; 11.27 + 11.28 virtual long unlink_object(const char *path, fileid_t fileid) = 0; 11.29 }; 11.30
12.1 --- a/libfsserver/include/fsserver/host_file_opener.h Fri Jan 14 01:10:35 2022 +0100 12.2 +++ b/libfsserver/include/fsserver/host_file_opener.h Thu Jan 27 23:45:17 2022 +0100 12.3 @@ -1,7 +1,7 @@ 12.4 /* 12.5 * An opener for a "host" file provided via the C library. 12.6 * 12.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 12.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 12.9 * 12.10 * This program is free software; you can redistribute it and/or 12.11 * modify it under the terms of the GNU General Public License as 12.12 @@ -75,6 +75,9 @@ 12.13 12.14 virtual long remove_object(const char *path, fileid_t fileid); 12.15 12.16 + virtual long rename_object(const char *source, fileid_t source_fileid, 12.17 + const char *target); 12.18 + 12.19 virtual long unlink_object(const char *path, fileid_t fileid); 12.20 }; 12.21
13.1 --- a/libfsserver/include/fsserver/opener_context_resource.h Fri Jan 14 01:10:35 2022 +0100 13.2 +++ b/libfsserver/include/fsserver/opener_context_resource.h Thu Jan 27 23:45:17 2022 +0100 13.3 @@ -1,7 +1,7 @@ 13.4 /* 13.5 * A context resource offering support for opening files. 13.6 * 13.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 13.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 13.9 * 13.10 * This program is free software; you can redistribute it and/or 13.11 * modify it under the terms of the GNU General Public License as 13.12 @@ -53,7 +53,7 @@ 13.13 13.14 /* Data access methods. */ 13.15 13.16 - char *get_path(); 13.17 + char *get_path(offset_t offset=0); 13.18 13.19 /* Opener context interface methods. */ 13.20 13.21 @@ -62,6 +62,8 @@ 13.22 13.23 long remove(); 13.24 13.25 + long rename(); 13.26 + 13.27 /* Pager/dataspace methods. */ 13.28 13.29 long map(unsigned long offset, address_t hot_spot, map_flags_t flags,
14.1 --- a/libfsserver/include/fsserver/opener_resource.h Fri Jan 14 01:10:35 2022 +0100 14.2 +++ b/libfsserver/include/fsserver/opener_resource.h Thu Jan 27 23:45:17 2022 +0100 14.3 @@ -1,7 +1,7 @@ 14.4 /* 14.5 * A resource offering support for creating contexts and opening files. 14.6 * 14.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 14.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 14.9 * 14.10 * This program is free software; you can redistribute it and/or 14.11 * modify it under the terms of the GNU General Public License as 14.12 @@ -36,10 +36,6 @@ 14.13 protected: 14.14 ResourceRegistry *_registry; 14.15 14.16 - /* Retrieval methods. */ 14.17 - 14.18 - virtual long get_parent(const char *path, fileid_t *fileid); 14.19 - 14.20 /* Notification methods. */ 14.21 14.22 virtual long notify_parent(const char *path); 14.23 @@ -65,6 +61,8 @@ 14.24 14.25 long remove(const char *path); 14.26 14.27 + long rename(const char *source, const char *target); 14.28 + 14.29 /* Opener interface methods. */ 14.30 14.31 long context(l4_cap_idx_t *context);
15.1 --- a/libfsserver/include/fsserver/resource_registry.h Fri Jan 14 01:10:35 2022 +0100 15.2 +++ b/libfsserver/include/fsserver/resource_registry.h Thu Jan 27 23:45:17 2022 +0100 15.3 @@ -53,6 +53,11 @@ 15.4 flags_t flags, fileid_t fileid, 15.5 Provider **provider); 15.6 15.7 + /* Provider manipulation methods. */ 15.8 + 15.9 + long _remove_provider(FileOpening *opening, const char *path, 15.10 + fileid_t fileid); 15.11 + 15.12 public: 15.13 explicit ResourceRegistry(Pages *pages); 15.14 15.15 @@ -70,6 +75,8 @@ 15.16 /* Provider manipulation methods. */ 15.17 15.18 long remove_provider(FileOpening *opening, const char *path); 15.19 + 15.20 + long rename_provider(FileOpening *opening, const char *source, const char *target); 15.21 }; 15.22 15.23 // vim: tabstop=4 expandtab shiftwidth=4
16.1 --- a/libfsserver/include/fsserver/test_file_opener.h Fri Jan 14 01:10:35 2022 +0100 16.2 +++ b/libfsserver/include/fsserver/test_file_opener.h Thu Jan 27 23:45:17 2022 +0100 16.3 @@ -1,7 +1,7 @@ 16.4 /* 16.5 * An opener for a test file containing generated content. 16.6 * 16.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 16.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 16.9 * 16.10 * This program is free software; you can redistribute it and/or 16.11 * modify it under the terms of the GNU General Public License as 16.12 @@ -56,6 +56,9 @@ 16.13 16.14 virtual long remove_object(const char *path, fileid_t fileid); 16.15 16.16 + virtual long rename_object(const char *source, fileid_t source_fileid, 16.17 + const char *target); 16.18 + 16.19 virtual long unlink_object(const char *path, fileid_t fileid); 16.20 }; 16.21
17.1 --- a/libfsserver/lib/Makefile Fri Jan 14 01:10:35 2022 +0100 17.2 +++ b/libfsserver/lib/Makefile Thu Jan 27 23:45:17 2022 +0100 17.3 @@ -56,6 +56,7 @@ 17.4 files/ext2_file_opener.cc \ 17.5 files/ext2_file_operations.cc \ 17.6 files/ext2_filesystem.cc \ 17.7 + files/file_opening.cc \ 17.8 files/file_pager.cc \ 17.9 files/file_provider.cc \ 17.10 files/filesystem_resource.cc \
18.1 --- a/libfsserver/lib/files/ext2_file_opener.cc Fri Jan 14 01:10:35 2022 +0100 18.2 +++ b/libfsserver/lib/files/ext2_file_opener.cc Thu Jan 27 23:45:17 2022 +0100 18.3 @@ -129,6 +129,31 @@ 18.4 return _ops->remove((ext2_ino_t) fileid); 18.5 } 18.6 18.7 +/* Rename a filesystem object, placing source inside the parent of target. */ 18.8 + 18.9 +long Ext2FileOpener::rename_object(const char *source, fileid_t source_fileid, 18.10 + const char *target) 18.11 +{ 18.12 + (void) source; 18.13 + 18.14 + fileid_t source_parent, target_parent; 18.15 + long err; 18.16 + 18.17 + err = get_parent(source, &source_parent); 18.18 + 18.19 + if (err) 18.20 + return err; 18.21 + 18.22 + err = get_parent(target, &target_parent); 18.23 + 18.24 + if (err) 18.25 + return err; 18.26 + 18.27 + return _ops->rename((ext2_ino_t) source_fileid, 18.28 + (ext2_ino_t) source_parent, path_basename(source), 18.29 + (ext2_ino_t) target_parent, path_basename(target)); 18.30 +} 18.31 + 18.32 /* Unlink a filesystem object. */ 18.33 18.34 long Ext2FileOpener::unlink_object(const char *path, fileid_t fileid)
19.1 --- a/libfsserver/lib/files/ext2_file_operations.cc Fri Jan 14 01:10:35 2022 +0100 19.2 +++ b/libfsserver/lib/files/ext2_file_operations.cc Thu Jan 27 23:45:17 2022 +0100 19.3 @@ -1,7 +1,7 @@ 19.4 /* 19.5 * File operations performed by an Ext2-compatible filesystem. 19.6 * 19.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 19.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 19.9 * 19.10 * This program is free software; you can redistribute it and/or 19.11 * modify it under the terms of the GNU General Public License as 19.12 @@ -129,6 +129,25 @@ 19.13 return L4_EOK; 19.14 } 19.15 19.16 +/* Rename an object. */ 19.17 + 19.18 +long Ext2FileOperations::rename(ext2_ino_t source, 19.19 + ext2_ino_t source_parent, const char *source_basename, 19.20 + ext2_ino_t target_parent, const char *target_basename) 19.21 +{ 19.22 + std::lock_guard<std::mutex> guard(_lock); 19.23 + 19.24 + errcode_t retval = image_rename(_fs, source, source_parent, source_basename, 19.25 + target_parent, target_basename); 19.26 + 19.27 + // NOTE: Map error conditions. 19.28 + 19.29 + if (retval) 19.30 + return -L4_EIO; 19.31 + 19.32 + return L4_EOK; 19.33 +} 19.34 + 19.35 /* Unlink an object from a directory. */ 19.36 19.37 long Ext2FileOperations::unlink(ext2_ino_t ino_parent, ext2_ino_t ino) 19.38 @@ -145,6 +164,8 @@ 19.39 return L4_EOK; 19.40 } 19.41 19.42 + 19.43 + 19.44 /* Obtain the size of a file. */ 19.45 19.46 offset_t Ext2FileOperations::get_size(ext2_file_t file)
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/libfsserver/lib/files/file_opening.cc Thu Jan 27 23:45:17 2022 +0100 20.3 @@ -0,0 +1,54 @@ 20.4 +/* 20.5 + * File opening support. 20.6 + * 20.7 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 20.8 + * 20.9 + * This program is free software; you can redistribute it and/or 20.10 + * modify it under the terms of the GNU General Public License as 20.11 + * published by the Free Software Foundation; either version 2 of 20.12 + * the License, or (at your option) any later version. 20.13 + * 20.14 + * This program is distributed in the hope that it will be useful, 20.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20.17 + * GNU General Public License for more details. 20.18 + * 20.19 + * You should have received a copy of the GNU General Public License 20.20 + * along with this program; if not, write to the Free Software 20.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20.22 + * Boston, MA 02110-1301, USA 20.23 + */ 20.24 + 20.25 +#include <stdlib.h> 20.26 +#include <string.h> 20.27 + 20.28 +#include "file_opening.h" 20.29 + 20.30 + 20.31 + 20.32 +/* Obtain the identifier for any active parent directory for a path. */ 20.33 + 20.34 +long FileOpening::get_parent(const char *path, fileid_t *fileid) 20.35 +{ 20.36 + char *sep = strrchr(path, (int) '/'); 20.37 + long err; 20.38 + 20.39 + /* For top-level paths, use the empty string to get the root directory. 20.40 + Otherwise, obtain the parent directory path to obtain the file 20.41 + identifier. */ 20.42 + 20.43 + if (sep == NULL) 20.44 + err = get_fileid("", 0, fileid); 20.45 + else 20.46 + { 20.47 + char *parent = strndup(path, sep - path + 1); 20.48 + 20.49 + parent[sep - path] = '\0'; 20.50 + err = get_fileid(parent, 0, fileid); 20.51 + free(parent); 20.52 + } 20.53 + 20.54 + return err; 20.55 +} 20.56 + 20.57 +// vim: tabstop=4 expandtab shiftwidth=4
21.1 --- a/libfsserver/lib/files/host_file_opener.cc Fri Jan 14 01:10:35 2022 +0100 21.2 +++ b/libfsserver/lib/files/host_file_opener.cc Thu Jan 27 23:45:17 2022 +0100 21.3 @@ -1,7 +1,7 @@ 21.4 /* 21.5 * An opener for a "host" file provided via the C library. 21.6 * 21.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 21.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 21.9 * 21.10 * This program is free software; you can redistribute it and/or 21.11 * modify it under the terms of the GNU General Public License as 21.12 @@ -19,6 +19,7 @@ 21.13 * Boston, MA 02110-1301, USA 21.14 */ 21.15 21.16 +#include <stdio.h> 21.17 #include <sys/stat.h> 21.18 #include <unistd.h> 21.19 21.20 @@ -140,6 +141,21 @@ 21.21 return L4_EOK; 21.22 } 21.23 21.24 +/* Rename a filesystem object, placing source inside the parent of target. */ 21.25 + 21.26 +long HostFileOpener::rename_object(const char *source, fileid_t source_fileid, 21.27 + const char *target) 21.28 +{ 21.29 + (void) source_fileid; 21.30 + 21.31 + /* NOTE: Should propagate a more meaningful error. */ 21.32 + 21.33 + if (rename(source, target)) 21.34 + return -L4_EIO; 21.35 + 21.36 + return L4_EOK; 21.37 +} 21.38 + 21.39 /* Unlink a filesystem object. */ 21.40 21.41 long HostFileOpener::unlink_object(const char *path, fileid_t fileid)
22.1 --- a/libfsserver/lib/files/opener_context_resource.cc Fri Jan 14 01:10:35 2022 +0100 22.2 +++ b/libfsserver/lib/files/opener_context_resource.cc Thu Jan 27 23:45:17 2022 +0100 22.3 @@ -50,9 +50,9 @@ 22.4 22.5 /* Data access methods. */ 22.6 22.7 -char *OpenerContextResource::get_path() 22.8 +char *OpenerContextResource::get_path(offset_t offset) 22.9 { 22.10 - char *buffer = _region->read(); 22.11 + char *buffer = _region->read(offset); 22.12 offset_t size = _region->size(); 22.13 22.14 /* Confine the path to the limit of the buffer. */ 22.15 @@ -88,4 +88,21 @@ 22.16 return _opener->remove(path); 22.17 } 22.18 22.19 +long OpenerContextResource::rename() 22.20 +{ 22.21 + char *source, *target; 22.22 + 22.23 + source = get_path(); 22.24 + 22.25 + if (source == NULL) 22.26 + return -L4_EINVAL; 22.27 + 22.28 + target = get_path(strlen(source) + 1); 22.29 + 22.30 + if (target == NULL) 22.31 + return -L4_EINVAL; 22.32 + 22.33 + return _opener->rename(source, target); 22.34 +} 22.35 + 22.36 // vim: tabstop=4 expandtab shiftwidth=4
23.1 --- a/libfsserver/lib/files/opener_resource.cc Fri Jan 14 01:10:35 2022 +0100 23.2 +++ b/libfsserver/lib/files/opener_resource.cc Thu Jan 27 23:45:17 2022 +0100 23.3 @@ -1,7 +1,7 @@ 23.4 /* 23.5 * A resource offering support for creating contexts and opening files. 23.6 * 23.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 23.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 23.9 * 23.10 * This program is free software; you can redistribute it and/or 23.11 * modify it under the terms of the GNU General Public License as 23.12 @@ -19,8 +19,6 @@ 23.13 * Boston, MA 02110-1301, USA 23.14 */ 23.15 23.16 -#include <string.h> 23.17 - 23.18 #include "opener_server.h" 23.19 #include "opener_resource.h" 23.20 #include "resource_server.h" 23.21 @@ -48,31 +46,6 @@ 23.22 23.23 23.24 23.25 -/* Obtain the identifier for any active parent directory for a path. */ 23.26 - 23.27 -long OpenerResource::get_parent(const char *path, fileid_t *fileid) 23.28 -{ 23.29 - char *sep = strrchr(path, (int) '/'); 23.30 - long err; 23.31 - 23.32 - /* For top-level paths, use the empty string to get the root directory. 23.33 - Otherwise, obtain the parent directory path to obtain the file 23.34 - identifier. */ 23.35 - 23.36 - if (sep == NULL) 23.37 - err = get_fileid("", 0, fileid); 23.38 - else 23.39 - { 23.40 - char *parent = strndup(path, sep - path + 1); 23.41 - 23.42 - parent[sep - path] = '\0'; 23.43 - err = get_fileid(parent, 0, fileid); 23.44 - free(parent); 23.45 - } 23.46 - 23.47 - return err; 23.48 -} 23.49 - 23.50 /* Obtain any active parent directory for a path, notifying its subscribers of 23.51 the file opening event. 23.52 NOTE: This might need to happen in the registry due to concurrency issues. */ 23.53 @@ -132,6 +105,13 @@ 23.54 return _registry->remove_provider(this, path); 23.55 } 23.56 23.57 +/* Request the renaming of the named filesystem object. */ 23.58 + 23.59 +long OpenerResource::rename(const char *source, const char *target) 23.60 +{ 23.61 + return _registry->rename_provider(this, source, target); 23.62 +} 23.63 + 23.64 23.65 23.66 /* Opener interface methods. */
24.1 --- a/libfsserver/lib/files/test_file_opener.cc Fri Jan 14 01:10:35 2022 +0100 24.2 +++ b/libfsserver/lib/files/test_file_opener.cc Thu Jan 27 23:45:17 2022 +0100 24.3 @@ -87,6 +87,15 @@ 24.4 return L4_EOK; 24.5 } 24.6 24.7 +/* Rename a filesystem object, placing source inside the parent of target. */ 24.8 + 24.9 +long TestFileOpener::rename_object(const char *source, fileid_t source_fileid, 24.10 + const char *target) 24.11 +{ 24.12 + (void) source; (void) source_fileid; (void) target; 24.13 + return -L4_EIO; 24.14 +} 24.15 + 24.16 /* Unlink a filesystem object. */ 24.17 24.18 long TestFileOpener::unlink_object(const char *path, fileid_t fileid)
25.1 --- a/libfsserver/lib/generic/resource_registry.cc Fri Jan 14 01:10:35 2022 +0100 25.2 +++ b/libfsserver/lib/generic/resource_registry.cc Thu Jan 27 23:45:17 2022 +0100 25.3 @@ -184,10 +184,16 @@ 25.4 if (err) 25.5 return err; 25.6 25.7 + return _remove_provider(opening, path, fileid); 25.8 +} 25.9 + 25.10 +long ResourceRegistry::_remove_provider(FileOpening *opening, const char *path, 25.11 + fileid_t fileid) 25.12 +{ 25.13 /* Obtain a provider for the object. */ 25.14 25.15 Provider *provider; 25.16 - err = find_provider(fileid, &provider); 25.17 + long err = find_provider(fileid, &provider); 25.18 25.19 if (err && (err != -L4_ENOENT)) 25.20 return err; 25.21 @@ -210,4 +216,94 @@ 25.22 return L4_EOK; 25.23 } 25.24 25.25 +/* Request the renaming of a filesystem object. */ 25.26 + 25.27 +long ResourceRegistry::rename_provider(FileOpening *opening, const char *source, 25.28 + const char *target) 25.29 +{ 25.30 + std::lock_guard<std::mutex> guard(_lock); 25.31 + 25.32 + long err; 25.33 + fileid_t source_fileid, target_fileid; 25.34 + 25.35 + /* Obtain an identifier for any recognised object. */ 25.36 + 25.37 + err = opening->get_fileid(source, 0, &source_fileid); 25.38 + 25.39 + if (err) 25.40 + return err; 25.41 + 25.42 + /* If source is a directory, the target must be a new directory or an empty 25.43 + directory. An empty directory will be replaced by the source 25.44 + directory. */ 25.45 + 25.46 + if (opening->accessing_directory(source, 0, source_fileid)) 25.47 + { 25.48 + err = opening->get_fileid(target, 0, &target_fileid); 25.49 + 25.50 + if (err && (err != -L4_ENOENT)) 25.51 + return err; 25.52 + 25.53 + /* Any existing directory must be empty. */ 25.54 + 25.55 + if (!err) 25.56 + { 25.57 + /* NOTE: Should really use the equivalent of ENOTDIR. */ 25.58 + 25.59 + if (!opening->accessing_directory(target, 0, target_fileid)) 25.60 + return -L4_EIO; 25.61 + 25.62 + /* NOTE: Test for empty directory. */ 25.63 + 25.64 + /* The existing directory will be removed. */ 25.65 + 25.66 + err = _remove_provider(opening, target, target_fileid); 25.67 + 25.68 + if (err) 25.69 + return err; 25.70 + } 25.71 + 25.72 + /* The source directory is moved within the filesystem to the parent of 25.73 + the indicated target. */ 25.74 + 25.75 + return opening->rename_object(source, source_fileid, target); 25.76 + } 25.77 + 25.78 + /* If source is a file, the target must be a new or existing file, not a 25.79 + directory. An existing file will be replaced. */ 25.80 + 25.81 + else if (opening->accessing_file(source, 0, source_fileid)) 25.82 + { 25.83 + err = opening->get_fileid(target, 0, &target_fileid); 25.84 + 25.85 + if (err && (err != -L4_ENOENT)) 25.86 + return err; 25.87 + 25.88 + if (!err) 25.89 + { 25.90 + /* NOTE: Should really use the equivalent of EISDIR. */ 25.91 + 25.92 + if (!opening->accessing_file(target, 0, target_fileid)) 25.93 + return -L4_EIO; 25.94 + 25.95 + /* The existing file will be removed. */ 25.96 + 25.97 + err = _remove_provider(opening, target, target_fileid); 25.98 + 25.99 + if (err) 25.100 + return err; 25.101 + } 25.102 + 25.103 + /* The source file is moved within the filesystem to the parent of the 25.104 + indicated target. */ 25.105 + 25.106 + return opening->rename_object(source, source_fileid, target); 25.107 + } 25.108 + 25.109 + /* NOTE: Other object types are to be supported. */ 25.110 + 25.111 + else 25.112 + return -L4_EIO; 25.113 +} 25.114 + 25.115 // vim: tabstop=4 expandtab shiftwidth=4
26.1 --- a/libsystypes/idl/opener_context.idl Fri Jan 14 01:10:35 2022 +0100 26.2 +++ b/libsystypes/idl/opener_context.idl Thu Jan 27 23:45:17 2022 +0100 26.3 @@ -23,6 +23,11 @@ 26.4 /* Remove a file using a path written to the context's dataspace. */ 26.5 26.6 [opcode(14)] void remove(); 26.7 + 26.8 + /* Rename a file within a filesystem using paths written to the context's 26.9 + dataspace. */ 26.10 + 26.11 + [opcode(15)] void rename(); 26.12 }; 26.13 26.14 /* vim: tabstop=2 expandtab shiftwidth=2
27.1 --- a/tests/Makefile Fri Jan 14 01:10:35 2022 +0100 27.2 +++ b/tests/Makefile Thu Jan 27 23:45:17 2022 +0100 27.3 @@ -8,6 +8,7 @@ 27.4 dstest_file_monitor \ 27.5 dstest_file_readdir \ 27.6 dstest_file_readdir_concurrent \ 27.7 + dstest_file_rename \ 27.8 dstest_host_client \ 27.9 dstest_pipe_client \ 27.10 dstest_test_client 27.11 @@ -28,6 +29,8 @@ 27.12 27.13 SRC_CC_dstest_file_readdir_concurrent = dstest_file_readdir_concurrent.cc 27.14 27.15 +SRC_CC_dstest_file_rename = dstest_file_rename.cc 27.16 + 27.17 SRC_CC_dstest_host_client = dstest_host_client.cc 27.18 27.19 SRC_CC_dstest_pipe_client = dstest_pipe_client.cc
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tests/dstest_file_rename.cc Thu Jan 27 23:45:17 2022 +0100 28.3 @@ -0,0 +1,161 @@ 28.4 +/* 28.5 + * Test renaming operations. 28.6 + * 28.7 + * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 28.8 + * 28.9 + * This program is free software; you can redistribute it and/or 28.10 + * modify it under the terms of the GNU General Public License as 28.11 + * published by the Free Software Foundation; either version 2 of 28.12 + * the License, or (at your option) any later version. 28.13 + * 28.14 + * This program is distributed in the hope that it will be useful, 28.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.17 + * GNU General Public License for more details. 28.18 + * 28.19 + * You should have received a copy of the GNU General Public License 28.20 + * along with this program; if not, write to the Free Software 28.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 28.22 + * Boston, MA 02110-1301, USA 28.23 + */ 28.24 + 28.25 +#include <l4/re/env.h> 28.26 +#include <l4/sys/err.h> 28.27 + 28.28 +#include <stdio.h> 28.29 +#include <string.h> 28.30 +#include <stdlib.h> 28.31 + 28.32 +#include <fsclient/client.h> 28.33 +#include <systypes/fcntl.h> 28.34 + 28.35 + 28.36 + 28.37 +static file_t *open_directory(char *filename, bool have_uid, sys_uid_t uid) 28.38 +{ 28.39 + /* With a user, open a user-specific file opener. */ 28.40 + 28.41 + if (have_uid) 28.42 + { 28.43 + l4_cap_idx_t opener = client_open_for_user((user_t) {uid, uid, 0022}); 28.44 + 28.45 + if (l4_is_invalid_cap(opener)) 28.46 + { 28.47 + printf("Could not obtain opener for file.\n"); 28.48 + return NULL; 28.49 + } 28.50 + 28.51 + /* Invoke the open method to receive the file reference. */ 28.52 + 28.53 + return client_opendir_using(filename, opener); 28.54 + } 28.55 + else 28.56 + { 28.57 + return client_opendir(filename); 28.58 + } 28.59 +} 28.60 + 28.61 +static long rename_file(char *source, char *target, bool have_uid, sys_uid_t uid) 28.62 +{ 28.63 + /* With a user, open a user-specific file opener. */ 28.64 + 28.65 + if (have_uid) 28.66 + { 28.67 + l4_cap_idx_t opener = client_open_for_user((user_t) {uid, uid, 0022}); 28.68 + 28.69 + if (l4_is_invalid_cap(opener)) 28.70 + { 28.71 + printf("Could not obtain opener for file.\n"); 28.72 + return -L4_EIO; 28.73 + } 28.74 + 28.75 + /* Invoke the rename method to rename the file. */ 28.76 + 28.77 + return client_rename_using(source, target, opener); 28.78 + } 28.79 + else 28.80 + { 28.81 + return client_rename(source, target); 28.82 + } 28.83 +} 28.84 + 28.85 + 28.86 + 28.87 +int main(int argc, char *argv[]) 28.88 +{ 28.89 + if (argc < 2) 28.90 + { 28.91 + printf("Need a directory name and an optional user identifier (if used with a filesystem).\n"); 28.92 + return 1; 28.93 + } 28.94 + 28.95 + char *filename = argv[1]; 28.96 + bool have_uid = (argc > 2) && strlen(argv[2]); 28.97 + sys_uid_t uid = have_uid ? atoi(argv[2]) : 0; 28.98 + 28.99 + printf("Opening %s...\n", filename); 28.100 + 28.101 + file_t *reader = open_directory(filename, have_uid, uid); 28.102 + 28.103 + if (reader == NULL) 28.104 + { 28.105 + printf("Could not read from directory.\n"); 28.106 + return 1; 28.107 + } 28.108 + 28.109 + printf("Reading...\n"); 28.110 + 28.111 + struct dirent *dirent; 28.112 + 28.113 + while ((dirent = client_readdir(reader)) != NULL) 28.114 + { 28.115 + printf("> %s\n", dirent->d_name); 28.116 + free(dirent); 28.117 + } 28.118 + 28.119 + printf("Directory shown.\n"); 28.120 + 28.121 + /* Rename some files. */ 28.122 + 28.123 + char source[strlen(filename) + strlen("/file-XXXX.txt") + 10]; 28.124 + char target[strlen(filename) + strlen("/file-XXXX.txt") + 10]; 28.125 + int filenum; 28.126 + 28.127 + for (filenum = 1; filenum < 100; filenum++) 28.128 + { 28.129 + sprintf(source, "%s/file-%d.txt", filename, filenum); 28.130 + sprintf(target, "%s/renamed-%d.txt", filename, filenum); 28.131 + 28.132 + long err = rename_file(source, target, have_uid, uid); 28.133 + 28.134 + if (err) 28.135 + { 28.136 + printf("Could not rename file: %s\n", source); 28.137 + return 1; 28.138 + } 28.139 + } 28.140 + 28.141 + /* Show the new listing. */ 28.142 + 28.143 + reader = open_directory(filename, have_uid, uid); 28.144 + 28.145 + if (reader == NULL) 28.146 + { 28.147 + printf("Could not read from directory.\n"); 28.148 + return 1; 28.149 + } 28.150 + 28.151 + printf("Reading...\n"); 28.152 + 28.153 + while ((dirent = client_readdir(reader)) != NULL) 28.154 + { 28.155 + printf("> %s\n", dirent->d_name); 28.156 + free(dirent); 28.157 + } 28.158 + 28.159 + printf("Directory shown.\n"); 28.160 + 28.161 + return 0; 28.162 +} 28.163 + 28.164 +// vim: tabstop=2 expandtab shiftwidth=2