aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-08-05 02:25:39 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-05 02:25:39 -0400
commit80813f2ba8ef2ed02100d2f6c04897b8d68b0857 (patch)
treec3a6fb4805250f82badc4a2eba37d21706261306
parent2755810159041a4b7ed41f322f30b2654e1d27b5 (diff)
downloaddbfs-80813f2ba8ef2ed02100d2f6c04897b8d68b0857.tar.gz
Move xattr-related code to new file xattr.c.
No code changes aside from making dbmeta_del() global.
-rw-r--r--Makefile.am2
-rw-r--r--dbfs-backend.c310
-rw-r--r--dbfs.h1
-rw-r--r--xattr.c314
4 files changed, 317 insertions, 310 deletions
diff --git a/Makefile.am b/Makefile.am
index dcf51fc..b9b3f32 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@ sbin_PROGRAMS = dbfs mkdbfs dbfsck
libdbfs_a_SOURCES = libdbfs.c
-dbfs_SOURCES = dbfs.c dbfs.h dbfs-backend.c
+dbfs_SOURCES = dbfs.c dbfs.h dbfs-backend.c xattr.c
dbfs_LDADD = @GLIB_LIBS@ @FUSE_LIBS@ @DB_LIBS@ libdbfs.a
mkdbfs_SOURCES = mkdbfs.c
diff --git a/dbfs-backend.c b/dbfs-backend.c
index 36d873a..4310a04 100644
--- a/dbfs-backend.c
+++ b/dbfs-backend.c
@@ -6,7 +6,6 @@
#include <errno.h>
#include <unistd.h>
#include <time.h>
-#include <attr/xattr.h>
#include <glib.h>
#include <db.h>
#include "dbfs.h"
@@ -30,7 +29,7 @@ struct dbfs_ext_list {
guint64 len; /* length of fragment */
};
-static int dbmeta_del(const char *key_str)
+int dbmeta_del(const char *key_str)
{
DBT key;
int rc;
@@ -587,313 +586,6 @@ err_out:
return rc;
}
-static int dbfs_xattr_list_read(DBT *key, DBT *val, char *keystr, guint64 ino)
-{
- snprintf(keystr, 32, "/xattr/%Lu", (unsigned long long) ino);
-
- memset(key, 0, sizeof(*key));
- key->data = keystr;
- key->size = strlen(keystr);
-
- memset(val, 0, sizeof(*val));
- val->flags = DB_DBT_MALLOC;
-
- return gfs->meta->get(gfs->meta, NULL, key, val, 0);
-}
-
-static int dbfs_xattr_list_add(guint64 ino, const char *name)
-{
- struct dbfs_xlist *ent;
- char keystr[32];
- DBT key, val;
- size_t alloc_len;
- size_t name_len = strlen(name);
- int rc;
-
- /* get list from db */
- rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
- if (rc && (rc != DB_NOTFOUND))
- return -EIO;
-
- alloc_len = dbfs_xlist_next(name_len);
-
- /* if list not found, create new one */
- if (rc == DB_NOTFOUND) {
- ent = malloc(alloc_len);
- if (!ent)
- return -ENOMEM;
-
- val.data = ent;
- val.size = alloc_len;
- }
-
- /* otherwise, append to existing list */
- else {
- void *mem;
- size_t old_size;
-
- alloc_len += val.size;
- mem = realloc(val.data, alloc_len);
- if (!mem) {
- rc = -ENOMEM;
- goto out;
- }
-
- old_size = val.size;
- val.data = mem;
- val.size = alloc_len;
-
- mem += old_size;
- ent = mem;
- }
-
- /* fill in list entry at tail of list */
- ent->namelen = GUINT32_TO_LE(name_len);
- memcpy(ent->name, name, name_len);
-
- /* store new list in db */
- rc = gfs->meta->put(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
-
-out:
- free(val.data);
- return rc;
-}
-
-static int dbfs_xattr_list_del(guint64 ino, const char *name)
-{
- size_t name_len = strlen(name);
- struct dbfs_xlist *ent;
- char keystr[32];
- DBT key, val;
- int rc;
- long bytes;
- void *mem;
- size_t ssize = 0;
- unsigned int entries = 0;
-
- /* get list from db */
- rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
- if (rc == DB_NOTFOUND)
- return -ENOENT;
- if (rc)
- return -EIO;
-
- /* find entry in list */
- mem = val.data;
- bytes = val.size;
- while (bytes > 0) {
- entries++;
- ent = mem;
- ssize = dbfs_xlist_next(GUINT32_FROM_LE(ent->namelen));
- if (ssize > bytes) { /* data corrupt */
- rc = -EIO;
- goto out;
- }
-
- if (!memcmp(ent->name, name, name_len))
- break;
-
- bytes -= ssize;
- }
-
- /* if not found, exit */
- if (bytes <= 0) {
- rc = -ENOENT;
- goto out;
- }
-
- /* if at least one entry will exist post-delete, update db */
- if (entries > 1) {
- /* swallow entry */
- memmove(mem, mem + ssize, bytes - ssize);
- val.size -= ssize;
-
- /* store new list in db */
- rc = gfs->meta->put(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
- }
-
- /* otherwise, delete db entry */
- else
- rc = dbmeta_del(keystr);
-
-out:
- free(val.data);
- return rc;
-}
-
-int dbfs_xattr_list(guint64 ino, void **buf_out, size_t *buflen_out)
-{
- struct dbfs_xlist *ent;
- char keystr[32];
- DBT key, val;
- void *mem, *name_list;
- size_t name_list_len, ssize, name_len;
- long bytes;
- char null = 0;
- int rc;
-
- *buf_out = NULL;
- *buflen_out = 0;
-
- /* get list from db */
- rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
- if (rc == DB_NOTFOUND)
- return 0;
- if (rc)
- return -EIO;
- if (val.size == 0)
- return 0;
-
- /* allocate output buffer */
- name_list = malloc(val.size);
- if (!name_list) {
- rc = -ENOMEM;
- goto out;
- }
- name_list_len = 0;
-
- /* fill output buffer */
- mem = val.data;
- bytes = val.size;
- while (bytes > 0) {
- ent = mem;
- name_len = GUINT32_FROM_LE(ent->namelen);
- ssize = dbfs_xlist_next(name_len);
-
- if (ssize > bytes) { /* data corrupt */
- rc = -EIO;
- goto out;
- }
-
- memcpy(name_list + name_list_len, ent->name, name_len);
- name_list_len += name_len;
-
- memcpy(name_list + name_list_len, &null, 1);
- name_list_len++;
-
- bytes -= ssize;
- }
-
- *buf_out = name_list;
- *buflen_out = name_list_len;
-
-out:
- free(val.data);
- 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 void *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,
- void **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 void *buf,
- size_t buflen, int flags)
-{
- void *current = NULL;
- size_t current_len = 0;
- size_t name_len = strlen(name);
- int rc, exists;
-
- if ((!name) || (!*name) || (name_len > DBFS_XATTR_NAME_LEN) ||
- (!g_utf8_validate(name, name_len, NULL)) ||
- (buflen > DBFS_XATTR_MAX_LEN))
- return -EINVAL;
-
- 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;
-
- rc = dbfs_xattr_write(ino_n, name, buf, buflen);
- if (rc)
- return rc;
-
- rc = dbfs_xattr_list_add(ino_n, name);
- if (rc) {
- dbfs_xattr_remove(ino_n, name, FALSE);
- return rc;
- }
-
- return 0;
-}
-
-int dbfs_xattr_remove(guint64 ino_n, const char *name, gboolean update_list)
-{
- char key_str[DBFS_XATTR_NAME_LEN + 32];
-
- snprintf(key_str, sizeof(key_str),
- "/xattr/%Lu/%s", (unsigned long long) ino_n, name);
-
- if (update_list) {
- int rc = dbfs_xattr_list_del(ino_n, name);
- if (rc)
- return rc;
- }
-
- return dbmeta_del(key_str);
-}
-
static void ext_list_free(GList *ext_list)
{
GList *tmp;
diff --git a/dbfs.h b/dbfs.h
index ed1e925..3f2c8b2 100644
--- a/dbfs.h
+++ b/dbfs.h
@@ -103,6 +103,7 @@ struct dbfs {
typedef int (*dbfs_dir_actor_t) (struct dbfs_dirent *, void *);
/* dbfs-backend.c */
+extern int dbmeta_del(const char *key_str);
extern int dbfs_inode_read(guint64 ino_n, struct dbfs_inode **ino_out);
extern int dbfs_dir_read(guint64 ino, DBT *val);
extern int dbfs_symlink_read(guint64 ino, DBT *val);
diff --git a/xattr.c b/xattr.c
new file mode 100644
index 0000000..abcdc82
--- /dev/null
+++ b/xattr.c
@@ -0,0 +1,314 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <attr/xattr.h>
+#include <db.h>
+#include "dbfs.h"
+
+static int dbfs_xattr_list_read(DBT *key, DBT *val, char *keystr, guint64 ino)
+{
+ snprintf(keystr, 32, "/xattr/%Lu", (unsigned long long) ino);
+
+ memset(key, 0, sizeof(*key));
+ key->data = keystr;
+ key->size = strlen(keystr);
+
+ memset(val, 0, sizeof(*val));
+ val->flags = DB_DBT_MALLOC;
+
+ return gfs->meta->get(gfs->meta, NULL, key, val, 0);
+}
+
+static int dbfs_xattr_list_add(guint64 ino, const char *name)
+{
+ struct dbfs_xlist *ent;
+ char keystr[32];
+ DBT key, val;
+ size_t alloc_len;
+ size_t name_len = strlen(name);
+ int rc;
+
+ /* get list from db */
+ rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
+ if (rc && (rc != DB_NOTFOUND))
+ return -EIO;
+
+ alloc_len = dbfs_xlist_next(name_len);
+
+ /* if list not found, create new one */
+ if (rc == DB_NOTFOUND) {
+ ent = malloc(alloc_len);
+ if (!ent)
+ return -ENOMEM;
+
+ val.data = ent;
+ val.size = alloc_len;
+ }
+
+ /* otherwise, append to existing list */
+ else {
+ void *mem;
+ size_t old_size;
+
+ alloc_len += val.size;
+ mem = realloc(val.data, alloc_len);
+ if (!mem) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ old_size = val.size;
+ val.data = mem;
+ val.size = alloc_len;
+
+ mem += old_size;
+ ent = mem;
+ }
+
+ /* fill in list entry at tail of list */
+ ent->namelen = GUINT32_TO_LE(name_len);
+ memcpy(ent->name, name, name_len);
+
+ /* store new list in db */
+ rc = gfs->meta->put(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
+
+out:
+ free(val.data);
+ return rc;
+}
+
+static int dbfs_xattr_list_del(guint64 ino, const char *name)
+{
+ size_t name_len = strlen(name);
+ struct dbfs_xlist *ent;
+ char keystr[32];
+ DBT key, val;
+ int rc;
+ long bytes;
+ void *mem;
+ size_t ssize = 0;
+ unsigned int entries = 0;
+
+ /* get list from db */
+ rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
+ if (rc == DB_NOTFOUND)
+ return -ENOENT;
+ if (rc)
+ return -EIO;
+
+ /* find entry in list */
+ mem = val.data;
+ bytes = val.size;
+ while (bytes > 0) {
+ entries++;
+ ent = mem;
+ ssize = dbfs_xlist_next(GUINT32_FROM_LE(ent->namelen));
+ if (ssize > bytes) { /* data corrupt */
+ rc = -EIO;
+ goto out;
+ }
+
+ if (!memcmp(ent->name, name, name_len))
+ break;
+
+ bytes -= ssize;
+ }
+
+ /* if not found, exit */
+ if (bytes <= 0) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ /* if at least one entry will exist post-delete, update db */
+ if (entries > 1) {
+ /* swallow entry */
+ memmove(mem, mem + ssize, bytes - ssize);
+ val.size -= ssize;
+
+ /* store new list in db */
+ rc = gfs->meta->put(gfs->meta, NULL, &key, &val, 0) ? -EIO : 0;
+ }
+
+ /* otherwise, delete db entry */
+ else
+ rc = dbmeta_del(keystr);
+
+out:
+ free(val.data);
+ return rc;
+}
+
+int dbfs_xattr_list(guint64 ino, void **buf_out, size_t *buflen_out)
+{
+ struct dbfs_xlist *ent;
+ char keystr[32];
+ DBT key, val;
+ void *mem, *name_list;
+ size_t name_list_len, ssize, name_len;
+ long bytes;
+ char null = 0;
+ int rc;
+
+ *buf_out = NULL;
+ *buflen_out = 0;
+
+ /* get list from db */
+ rc = dbfs_xattr_list_read(&key, &val, keystr, ino);
+ if (rc == DB_NOTFOUND)
+ return 0;
+ if (rc)
+ return -EIO;
+ if (val.size == 0)
+ return 0;
+
+ /* allocate output buffer */
+ name_list = malloc(val.size);
+ if (!name_list) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ name_list_len = 0;
+
+ /* fill output buffer */
+ mem = val.data;
+ bytes = val.size;
+ while (bytes > 0) {
+ ent = mem;
+ name_len = GUINT32_FROM_LE(ent->namelen);
+ ssize = dbfs_xlist_next(name_len);
+
+ if (ssize > bytes) { /* data corrupt */
+ rc = -EIO;
+ goto out;
+ }
+
+ memcpy(name_list + name_list_len, ent->name, name_len);
+ name_list_len += name_len;
+
+ memcpy(name_list + name_list_len, &null, 1);
+ name_list_len++;
+
+ bytes -= ssize;
+ }
+
+ *buf_out = name_list;
+ *buflen_out = name_list_len;
+
+out:
+ free(val.data);
+ 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 void *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,
+ void **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 void *buf,
+ size_t buflen, int flags)
+{
+ void *current = NULL;
+ size_t current_len = 0;
+ size_t name_len = strlen(name);
+ int rc, exists;
+
+ if ((!name) || (!*name) || (name_len > DBFS_XATTR_NAME_LEN) ||
+ (!g_utf8_validate(name, name_len, NULL)) ||
+ (buflen > DBFS_XATTR_MAX_LEN))
+ return -EINVAL;
+
+ 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;
+
+ rc = dbfs_xattr_write(ino_n, name, buf, buflen);
+ if (rc)
+ return rc;
+
+ rc = dbfs_xattr_list_add(ino_n, name);
+ if (rc) {
+ dbfs_xattr_remove(ino_n, name, FALSE);
+ return rc;
+ }
+
+ return 0;
+}
+
+int dbfs_xattr_remove(guint64 ino_n, const char *name, gboolean update_list)
+{
+ char key_str[DBFS_XATTR_NAME_LEN + 32];
+
+ snprintf(key_str, sizeof(key_str),
+ "/xattr/%Lu/%s", (unsigned long long) ino_n, name);
+
+ if (update_list) {
+ int rc = dbfs_xattr_list_del(ino_n, name);
+ if (rc)
+ return rc;
+ }
+
+ return dbmeta_del(key_str);
+}
+