+std::string VfsCatalog::vfsPathByRFN(const std::string& rfn) throw (DmException)
+{
+ std::string curdir, path;
+ struct stat entry;
+ FILE *f;
+
+ curdir = rfn2path(rfn);
+ if (curdir.empty())
+ vfsThrow(EINVAL, "server or path required in replica file name");
+
+ if (vfsCheckPermissions("", S_IREAD))
+ vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str());
+
+ // read the catalog path
+ curdir = this->prefix_ + "/" + VFS_REPLICAS_TREE + curdir;
+ try {
+ wrapCall(stat(curdir.c_str(), &entry), "could not stat replica entry '%s'", rfn.c_str());
+ if (!S_ISREG(entry.st_mode))
+ vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' is not valid", rfn.c_str());
+ if ((f = fopen(curdir.c_str(), "r")) == NULL)
+ vfsThrowErrno("could not open replica entry '%s'", rfn.c_str());
+ } catch (DmException e) {
+ if (e.code() == ENOTDIR || e.code() == ENOENT)
+ vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' not found", rfn.c_str());
+ throw;
+ }
+ try {
+ fgets(this->buffer, sizeof this->buffer, f);
+ wrapCall(ferror(f), "error reading replica entry '%s'", rfn.c_str());
+ } catch (DmException e) {
+ fclose(f);
+ throw;
+ }
+ wrapCall(fclose(f), "could not close replica entry '%s'", rfn.c_str());
+
+ path = this->buffer;
+
+ return path;
+}
+
+
+
+ExtendedStat VfsCatalog::extendedStatByRFN(const std::string& rfn) throw (DmException)
+{
+ ExtendedStat meta;
+ std::string path;
+ Extensible xattrs;
+
+ path = vfsPathByRFN(rfn);
+ meta = vfsExtendedStat(path, true, false, false);
+
+ //
+ // User extended attributes are not supported on symlinks. We need the same
+ // owner, permissions and other atributes like the original file anyway.
+ // ==> always follow the symlinks.
+ //
+ try {
+ xattrs = vfsGetXattrs(path, getLocalPath(path), true, VFS_XATTR_TYPE_ALL);
+ } catch (DmException& e) {
+ // ignore - default owner and no ACLs
+ }
+ // use the retrieved xattrs
+ vfsUpdateExtendedStat(meta, xattrs);
+
+ vfsUpdateInode(meta, path);
+
+ return meta;
+}
+
+
+
bool VfsCatalog::access(const std::string& path, int mode) throw (DmException)
{
ExtendedStat meta;
bool VfsCatalog::accessReplica(const std::string& replica, int mode) throw (DmException)
{
- vfsThrow(ENOSYS, "searching by replica file names not supported");
- return false;
+ std::string path;
+
+ path = vfsPathByRFN(replica);
+ return this->access(path, mode);
}
Replica VfsCatalog::getReplicaByRFN(const std::string& rfn) throw (DmException)
{
+ std::string path;
+ ExtendedStat meta;
Replica replica;
- struct stat fstat;
-
- if (vfsCheckPermissions(rfn, S_IREAD))
- vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str());
+ Extensible::const_iterator it;
- wrapCall(stat(getLocalPath(rfn).c_str(), &fstat));
-
- replica.atime = fstat.st_atime;
- replica.fileid = fstat.st_ino;
- replica.ltime = 0;
- replica.nbaccesses = 0;
- replica.ptime = 0;
- replica.replicaid = 0;
- replica.rfn = rfn;
- replica.server = this->hostName_;
- replica.status = Replica::kAvailable;
- replica.type = Replica::kPermanent;
+ path = vfsPathByRFN(rfn);
+ meta = vfsExtendedStat(path, true, false, true);
+
+ vfsUpdateInode(meta, path);
+
+ // look for rfn in replicas
+ for (it = meta.begin(); it != meta.end(); it++) {
+ std::string key, value, value2, repidstr;
+
+ key = it->first;
+ if (key.compare(0, VFS_XATTR_LENGTH + 8, VFS_XATTR "replica.") == 0) {
+ repidstr = key.c_str() + VFS_XATTR_LENGTH + 8;
+ value = Extensible::anyToString(it->second);
+ value2 = meta.getString(VFS_XATTR "repattrs." + repidstr, "");
+
+ replica = replicaDeserialize(value, value2);
+ replica.replicaid = atoll(repidstr.c_str());
+ replica.fileid = meta.stat.st_ino;
+ if (rfn.compare(replica.rfn) == 0) break;
+ }
+ }
+
+ if (it == meta.end()) {
+ //
+ // Internal Inconsistency:
+ // Replica entry found but detailed info is missing in attributes.
+ //
+ vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' found in '%s', but detailed info missing", rfn.c_str(), path.c_str());
+ }
+
return replica;
}
std::string getWorkingDir (void) throw (DmException);
ExtendedStat extendedStat(const std::string&, bool = true) throw (DmException);
+ ExtendedStat extendedStatByRFN(const std::string& rfn) throw (DmException);
bool access(const std::string& path, int mode) throw (DmException);
bool accessReplica(const std::string& replica, int mode) throw (DmException);
void vfsUpdateExtendedStat(ExtendedStat &xStat, Extensible xattrs) throw (DmException);
ExtendedStat vfsSimpleStat(const std::string& name, const std::string& path, const std::string& lpath, bool follow, bool perms, bool replicas) throw (DmException);
ExtendedStat vfsExtendedStat(const std::string& path, bool follow = true, bool perms = true, bool replicas = false) throw (DmException);
+ std::string vfsPathByRFN(const std::string& rfn) throw (DmException);
PrivateDir* vfsOpenDir(const std::string& lpath, const std::string& path) throw (DmException);
Extensible vfsGetXattrs(const std::string& path, const std::string& lpath, bool follow, int amount) throw (DmException);
std::string vfsGetXattr(const std::string& path, const std::string &lpath, const std::string key, int flags);