using namespace dmlite;
+static void pathGetParts(const std::string &path, std::string &dirName, std::string& baseName);
+
VfsCatalog::VfsCatalog(const std::string& host) throw (DmException): Catalog(),
hostName_(host)
{
ExtendedStat xStat;
struct stat fstat;
+ FILE *f;
+ char buf[100];
+ size_t l;
+ std::string *aclstr;
if (follow)
wrapCall(stat(path.c_str(), &fstat));
xStat.status = ExtendedStat::kOnline;
xStat["pool"] = std::string("vfs");
+ if ((f = fopen(VFS_METAFILE_PREFIX, "r")) == NULL) {
+ if (errno != ENOENT) vfsThrowErrno("opening directory metadata failed");
+ } else {
+ l = fread(buf, 1, sizeof(buf) - 1, f);
+ if (ferror(f)) vfsThrow(DMLITE_SYSERR(EIO), "reading directory metadata failed");
+ buf[l] = '\0';
+ try {
+ xStat.acl = Acl(std::string(buf));
+ } catch (...) {
+ fclose(f);
+ throw;
+ }
+ wrapCall(fclose(f), "closing directory metadata failed");
+ }
+
return xStat;
}
-void VfsCatalog::unlink(const std::string& path) throw (DmException)
+static void rawUnlink(const std::string& path) throw (DmException)
{
wrapCall(::unlink(path.c_str()));
}
+void VfsCatalog::unlink(const std::string& path) throw (DmException)
+{
+ std::string dir, name;
+
+ pathGetParts(path, dir, name);
+ try {
+ rawUnlink(dir + "/" + VFS_METAFILE_PREFIX + name);
+ } catch (dmlite::DmException& e) {
+ if (e.code() != ENOENT) throw;
+ }
+ rawUnlink(path);
+}
+
+
void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException)
{
void VfsCatalog::setAcl(const std::string& path, const Acl& acl) throw (DmException)
{
- throw DmException(EACCES, "Write mode not supported");
+ ExtendedStat meta = this->extendedStat(path, false);
+ Acl aclCopy(acl);
+ mode_t oldmode;
+ std::string aclstr, parentPath, fileName;
+ FILE *f;
+
+//FIXME: who can set ACLs?
+
+ // Make sure the owner and group matches!
+ for (size_t i = 0; i < aclCopy.size(); i++) {
+ if (aclCopy[i].type == AclEntry::kUserObj)
+ aclCopy[i].id = meta.stat.st_uid;
+ else if (aclCopy[i].type == AclEntry::kGroupObj)
+ aclCopy[i].id = meta.stat.st_gid;
+ else if (aclCopy[i].type & AclEntry::kDefault && !S_ISDIR(meta.stat.st_mode))
+ vfsThrow(EINVAL, "Defaults can be only applied to directories");
+ }
+
+ // Validate the ACL
+ aclCopy.validate();
+
+ // Update the file mode
+ oldmode = meta.stat.st_mode;
+ for (size_t i = 0; i < aclCopy.size(); i++) {
+ switch (aclCopy[i].type) {
+ case AclEntry::kUserObj:
+ meta.stat.st_mode = (meta.stat.st_mode & 0177077) |
+ (aclCopy[i].perm << 6);
+ break;
+ case AclEntry::kGroupObj:
+ meta.stat.st_mode = (meta.stat.st_mode & 0177707) |
+ (aclCopy[i].perm << 3);
+ break;
+ case AclEntry::kMask:
+ meta.stat.st_mode = (meta.stat.st_mode & ~070) |
+ (meta.stat.st_mode & aclCopy[i].perm << 3);
+ break;
+ case AclEntry::kOther:
+ meta.stat.st_mode = (meta.stat.st_mode & 0177770) |
+ (aclCopy[i].perm);
+ break;
+ default:
+ continue;
+ }
+ }
+
+ if (oldmode != meta.stat.st_mode) {
+ wrapCall(chmod(path.c_str(), meta.stat.st_mode));
+ }
+
+ aclstr = aclCopy.serialize();
+ if (S_ISDIR(meta.stat.st_mode)) {
+ f = fopen((path + "/" + VFS_METAFILE_PREFIX).c_str(), "w");
+ wrapCall(f, "creating directory metadata failed");
+ } else {
+ pathGetParts(path, parentPath, fileName);
+ f = fopen((parentPath + "/" + VFS_METAFILE_PREFIX + fileName).c_str(), "w");
+ wrapCall(f, "creating file metadata failed");
+ }
+ fprintf(f, "%s", aclstr.c_str());
+ wrapCall(fclose(f), "closing metadata failed");
}
void VfsCatalog::removeDir(const std::string& path) throw (DmException)
{
- wrapCall(rmdir(path.c_str()));
+ try {
+ VfsCatalog::unlink(path + "/" + VFS_METAFILE_PREFIX);
+ } catch (dmlite::DmException& e) {
+ if (e.code() != ENOENT) throw;
+ }
+ wrapCall(::rmdir(path.c_str()));
}
{
// Nothing
}
+
+
+static void pathGetParts(const std::string &path, std::string &dirName, std::string& baseName) {
+ std::vector<std::string> components = Url::splitPath(path);
+ baseName = components.back();
+ components.pop_back();
+ dirName = Url::joinPath(components);
+}