aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-08-04 08:42:17 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-04 08:42:17 -0400
commitc8f869f43eda037b0e6c7be24a2fdb5dec4bab1b (patch)
treece29a49bf74e279247d81c49b3207ef75f31ebe3
parente9acf7d8ceb1b8b2772ab87cac74ea112cb94a5b (diff)
downloaddbfs-c8f869f43eda037b0e6c7be24a2fdb5dec4bab1b.tar.gz
Implement getxattr, setxattr, removexattr ops.
Also, two cleanups: - move key, val memset(3) closer to other key, val initialization - simplify expression 'rc ? -rc : 0'
-rw-r--r--dbfs-backend.c126
-rw-r--r--dbfs.c52
-rw-r--r--dbfs.h9
3 files changed, 170 insertions, 17 deletions
diff --git a/dbfs-backend.c b/dbfs-backend.c
index 34c9fc3..14eeb2b 100644
--- a/dbfs-backend.c
+++ b/dbfs-backend.c
@@ -6,6 +6,7 @@
#include <errno.h>
#include <unistd.h>
#include <time.h>
+#include <attr/xattr.h>
#include <glib.h>
#include <db.h>
#include "dbfs.h"
@@ -108,14 +109,13 @@ int dbfs_inode_read(guint64 ino_n, struct dbfs_inode **ino_out)
size_t ex_sz;
guint32 mode;
- memset(&key, 0, sizeof(key));
- memset(&val, 0, sizeof(val));
-
sprintf(key_str, "/inode/%Lu", (unsigned long long) ino_n);
+ memset(&key, 0, sizeof(key));
key.data = key_str;
key.size = strlen(key_str);
+ memset(&val, 0, sizeof(val));
val.flags = DB_DBT_MALLOC;
rc = gfs->meta->get(gfs->meta, NULL, &key, &val, 0);
@@ -197,14 +197,13 @@ int dbfs_dir_read(guint64 ino, DBT *val)
char key_str[32];
int rc;
- memset(&key, 0, sizeof(key));
- memset(val, 0, sizeof(*val));
-
sprintf(key_str, "/dir/%Lu", (unsigned long long) ino);
+ memset(&key, 0, sizeof(key));
key.data = key_str;
key.size = strlen(key_str);
+ memset(val, 0, sizeof(*val));
val->flags = DB_DBT_MALLOC;
rc = gfs->meta->get(gfs->meta, NULL, &key, val, 0);
@@ -431,14 +430,13 @@ int dbfs_symlink_read(guint64 ino, DBT *val)
char key_str[32];
int rc;
- memset(&key, 0, sizeof(key));
- memset(val, 0, sizeof(*val));
-
sprintf(key_str, "/symlink/%Lu", (unsigned long long) ino);
+ memset(&key, 0, sizeof(key));
key.data = key_str;
key.size = strlen(key_str);
+ memset(val, 0, sizeof(*val));
val->flags = DB_DBT_MALLOC;
rc = gfs->meta->get(gfs->meta, NULL, &key, val, 0);
@@ -452,14 +450,13 @@ int dbfs_symlink_write(guint64 ino, const char *link)
DBT key, val;
char key_str[32];
- memset(&key, 0, sizeof(key));
- memset(&val, 0, sizeof(val));
-
sprintf(key_str, "/symlink/%Lu", (unsigned long long) ino);
+ memset(&key, 0, sizeof(key));
key.data = key_str;
key.size = strlen(key_str);
+ memset(&val, 0, sizeof(val));
val.data = (void *) link;
val.size = strlen(link);
@@ -584,3 +581,108 @@ err_out:
return rc;
}
+static int dbfs_xattr_read(guint64 ino, const char *name, DBT *val)
+{
+ char key_str[DBFS_XATTR_NAME_LEN + 32];
+ DBT key;
+ int rc;
+
+ snprintf(key_str, sizeof(key_str),
+ "/xattr/%Lu/%s", (unsigned long long) ino, name);
+
+ memset(&key, 0, sizeof(key));
+ key.data = key_str;
+ key.size = strlen(key_str);
+
+ memset(val, 0, sizeof(*val));
+ val->flags = DB_DBT_MALLOC;
+
+ rc = gfs->meta->get(gfs->meta, NULL, &key, val, 0);
+ if (rc == DB_NOTFOUND)
+ return -EINVAL;
+ return rc ? -EIO : 0;
+}
+
+static int dbfs_xattr_write(guint64 ino, const char *name,
+ const char *buf, size_t buflen)
+{
+ char key_str[DBFS_XATTR_NAME_LEN + 32];
+ DBT key, val;
+
+ snprintf(key_str, sizeof(key_str),
+ "/xattr/%Lu/%s", (unsigned long long) ino, name);
+
+ memset(&key, 0, sizeof(key));
+ key.data = key_str;
+ key.size = strlen(key_str);
+
+ memset(&val, 0, sizeof(val));
+ val.data = (void *) buf;
+ val.size = buflen;
+
+ return gfs->meta->put(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
+}
+
+int dbfs_xattr_get(guint64 ino_n, const char *name,
+ char **buf_out, size_t *buflen_out)
+{
+ int rc;
+ DBT val;
+
+ rc = dbfs_xattr_read(ino_n, name, &val);
+ if (rc)
+ return rc;
+
+ *buf_out = val.data;
+ *buflen_out = val.size;
+
+ return 0;
+}
+
+int dbfs_xattr_set(guint64 ino_n, const char *name, const char *buf,
+ size_t buflen, int flags)
+{
+ char *current = NULL;
+ size_t current_len = 0;
+ int rc, exists;
+
+ rc = dbfs_xattr_get(ino_n, name, &current, &current_len);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ exists = (current == NULL);
+ free(current);
+
+ if (exists && (flags & XATTR_CREATE))
+ return -EEXIST;
+ if (!exists && (flags & XATTR_REPLACE))
+ return -ENOATTR;
+ if (buflen > DBFS_XATTR_MAX_LEN)
+ return -ENOSPC; /* TODO: return value sane? */
+
+ /* FIXME: update list of xattrs for this inode */
+
+ return dbfs_xattr_write(ino_n, name, buf, buflen);
+}
+
+int dbfs_xattr_remove(guint64 ino_n, const char *name)
+{
+ char key_str[DBFS_XATTR_NAME_LEN + 32];
+ DBT key;
+ int rc;
+
+ snprintf(key_str, sizeof(key_str),
+ "/xattr/%Lu/%s", (unsigned long long) ino_n, name);
+
+ memset(&key, 0, sizeof(key));
+ key.data = key_str;
+ key.size = strlen(key_str);
+
+ /* FIXME: update list of xattrs for this inode */
+
+ rc = gfs->meta->del(gfs->meta, NULL, &key, 0);
+ if (rc == DB_NOTFOUND)
+ return -ENOENT;
+ return rc ? -EIO : 0;
+}
+
diff --git a/dbfs.c b/dbfs.c
index 10a7906..d665cf0 100644
--- a/dbfs.c
+++ b/dbfs.c
@@ -212,7 +212,7 @@ static void dbfs_op_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
static void dbfs_op_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
{
int rc = dbfs_unlink(parent, name, 0);
- fuse_reply_err(req, rc ? -rc : 0);
+ fuse_reply_err(req, -rc);
}
static void dbfs_op_link(fuse_req_t req, fuse_ino_t ino_n, fuse_ino_t parent,
@@ -278,7 +278,7 @@ static void dbfs_op_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
rc = dbfs_unlink(parent, name, DBFS_UNLINK_DIR);
out:
- fuse_reply_err(req, rc ? -rc : 0);
+ fuse_reply_err(req, -rc);
}
static void dbfs_op_symlink(fuse_req_t req, const char *link,
@@ -402,6 +402,48 @@ static void dbfs_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
free(b.p);
}
+static void dbfs_op_setxattr(fuse_req_t req, fuse_ino_t ino,
+ const char *name, const char *value,
+ size_t size, int flags)
+{
+ int rc = dbfs_xattr_set(ino, name, value, size, flags);
+ fuse_reply_err(req, -rc);
+}
+
+static void dbfs_op_getxattr(fuse_req_t req, fuse_ino_t ino,
+ const char *name, size_t size)
+{
+ char *buf = NULL;
+ size_t buflen = 0;
+ int rc;
+
+ rc = dbfs_xattr_get(ino, name, &buf, &buflen);
+ if (rc)
+ goto err_out;
+
+ if (size == 0)
+ fuse_reply_xattr(req, buflen);
+ else if (buflen <= size)
+ fuse_reply_buf(req, buf, buflen);
+ else {
+ rc = -ERANGE;
+ goto err_out;
+ }
+
+ free(buf);
+ return;
+
+err_out:
+ fuse_reply_err(req, -rc);
+}
+
+static void dbfs_op_removexattr(fuse_req_t req, fuse_ino_t ino,
+ const char *name)
+{
+ int rc = dbfs_xattr_remove(ino, name);
+ fuse_reply_err(req, -rc);
+}
+
static struct fuse_lowlevel_ops dbfs_ops = {
.init = dbfs_op_init,
.destroy = dbfs_op_destroy,
@@ -428,10 +470,10 @@ static struct fuse_lowlevel_ops dbfs_ops = {
.releasedir = dbfs_op_releasedir,
.fsyncdir = NULL,
.statfs = NULL,
- .setxattr = NULL,
- .getxattr = NULL,
+ .setxattr = dbfs_op_setxattr,
+ .getxattr = dbfs_op_getxattr,
.listxattr = NULL,
- .removexattr = NULL,
+ .removexattr = dbfs_op_removexattr,
.access = NULL,
.create = NULL,
};
diff --git a/dbfs.h b/dbfs.h
index 220a02f..5e22788 100644
--- a/dbfs.h
+++ b/dbfs.h
@@ -13,6 +13,9 @@ enum {
DBFS_ROOT_INO = 1,
DBFS_DIRENT_ALIGN = 8,
+
+ DBFS_XATTR_NAME_LEN = 256,
+ DBFS_XATTR_MAX_LEN = (1024 * 1024),
};
enum {
@@ -95,6 +98,12 @@ extern int dbfs_mknod(guint64 parent, const char *name,
struct dbfs_inode **ino);
extern int dbfs_symlink_write(guint64 ino, const char *link);
extern int dbfs_inode_del(struct dbfs_inode *ino);
+extern int dbfs_xattr_get(guint64 ino_n, const char *name,
+ char **buf_out, size_t *buflen_out);
+extern int dbfs_xattr_set(guint64 ino_n, const char *name,
+ const char *buf, size_t buflen,
+ int flags);
+extern int dbfs_xattr_remove(guint64 ino_n, const char *name);
/* libdbfs.c */
extern int dbfs_open(struct dbfs *fs);