diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-04 08:42:17 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-04 08:42:17 -0400 |
commit | c8f869f43eda037b0e6c7be24a2fdb5dec4bab1b (patch) | |
tree | ce29a49bf74e279247d81c49b3207ef75f31ebe3 | |
parent | e9acf7d8ceb1b8b2772ab87cac74ea112cb94a5b (diff) | |
download | dbfs-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.c | 126 | ||||
-rw-r--r-- | dbfs.c | 52 | ||||
-rw-r--r-- | dbfs.h | 9 |
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, ¤t, ¤t_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; +} + @@ -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, }; @@ -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); |