diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-05 02:25:39 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-05 02:25:39 -0400 |
commit | 80813f2ba8ef2ed02100d2f6c04897b8d68b0857 (patch) | |
tree | c3a6fb4805250f82badc4a2eba37d21706261306 | |
parent | 2755810159041a4b7ed41f322f30b2654e1d27b5 (diff) | |
download | dbfs-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.am | 2 | ||||
-rw-r--r-- | dbfs-backend.c | 310 | ||||
-rw-r--r-- | dbfs.h | 1 | ||||
-rw-r--r-- | xattr.c | 314 |
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, ¤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; - - 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; @@ -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); @@ -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, ¤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; + + 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); +} + |