1.1 --- a/libfsserver/lib/generic/resource_registry.cc Fri Jan 14 01:10:35 2022 +0100
1.2 +++ b/libfsserver/lib/generic/resource_registry.cc Thu Jan 27 23:45:17 2022 +0100
1.3 @@ -184,10 +184,16 @@
1.4 if (err)
1.5 return err;
1.6
1.7 + return _remove_provider(opening, path, fileid);
1.8 +}
1.9 +
1.10 +long ResourceRegistry::_remove_provider(FileOpening *opening, const char *path,
1.11 + fileid_t fileid)
1.12 +{
1.13 /* Obtain a provider for the object. */
1.14
1.15 Provider *provider;
1.16 - err = find_provider(fileid, &provider);
1.17 + long err = find_provider(fileid, &provider);
1.18
1.19 if (err && (err != -L4_ENOENT))
1.20 return err;
1.21 @@ -210,4 +216,94 @@
1.22 return L4_EOK;
1.23 }
1.24
1.25 +/* Request the renaming of a filesystem object. */
1.26 +
1.27 +long ResourceRegistry::rename_provider(FileOpening *opening, const char *source,
1.28 + const char *target)
1.29 +{
1.30 + std::lock_guard<std::mutex> guard(_lock);
1.31 +
1.32 + long err;
1.33 + fileid_t source_fileid, target_fileid;
1.34 +
1.35 + /* Obtain an identifier for any recognised object. */
1.36 +
1.37 + err = opening->get_fileid(source, 0, &source_fileid);
1.38 +
1.39 + if (err)
1.40 + return err;
1.41 +
1.42 + /* If source is a directory, the target must be a new directory or an empty
1.43 + directory. An empty directory will be replaced by the source
1.44 + directory. */
1.45 +
1.46 + if (opening->accessing_directory(source, 0, source_fileid))
1.47 + {
1.48 + err = opening->get_fileid(target, 0, &target_fileid);
1.49 +
1.50 + if (err && (err != -L4_ENOENT))
1.51 + return err;
1.52 +
1.53 + /* Any existing directory must be empty. */
1.54 +
1.55 + if (!err)
1.56 + {
1.57 + /* NOTE: Should really use the equivalent of ENOTDIR. */
1.58 +
1.59 + if (!opening->accessing_directory(target, 0, target_fileid))
1.60 + return -L4_EIO;
1.61 +
1.62 + /* NOTE: Test for empty directory. */
1.63 +
1.64 + /* The existing directory will be removed. */
1.65 +
1.66 + err = _remove_provider(opening, target, target_fileid);
1.67 +
1.68 + if (err)
1.69 + return err;
1.70 + }
1.71 +
1.72 + /* The source directory is moved within the filesystem to the parent of
1.73 + the indicated target. */
1.74 +
1.75 + return opening->rename_object(source, source_fileid, target);
1.76 + }
1.77 +
1.78 + /* If source is a file, the target must be a new or existing file, not a
1.79 + directory. An existing file will be replaced. */
1.80 +
1.81 + else if (opening->accessing_file(source, 0, source_fileid))
1.82 + {
1.83 + err = opening->get_fileid(target, 0, &target_fileid);
1.84 +
1.85 + if (err && (err != -L4_ENOENT))
1.86 + return err;
1.87 +
1.88 + if (!err)
1.89 + {
1.90 + /* NOTE: Should really use the equivalent of EISDIR. */
1.91 +
1.92 + if (!opening->accessing_file(target, 0, target_fileid))
1.93 + return -L4_EIO;
1.94 +
1.95 + /* The existing file will be removed. */
1.96 +
1.97 + err = _remove_provider(opening, target, target_fileid);
1.98 +
1.99 + if (err)
1.100 + return err;
1.101 + }
1.102 +
1.103 + /* The source file is moved within the filesystem to the parent of the
1.104 + indicated target. */
1.105 +
1.106 + return opening->rename_object(source, source_fileid, target);
1.107 + }
1.108 +
1.109 + /* NOTE: Other object types are to be supported. */
1.110 +
1.111 + else
1.112 + return -L4_EIO;
1.113 +}
1.114 +
1.115 // vim: tabstop=4 expandtab shiftwidth=4