aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-04-23 05:10:47 -0400
committerJeff Garzik <jeff@garzik.org>2006-04-23 05:10:47 -0400
commitf0ca20ceef8d1187f9645b628f4a1a36f9db87a1 (patch)
tree297afabd97b7f8a8792ec3d2e33cecaabb017c42
parent7c95682509cf22ad3ec3e3576c725824e880c980 (diff)
downloaddbfs-f0ca20ceef8d1187f9645b628f4a1a36f9db87a1.tar.gz
dbfs: abstract out dir lookup, dir foreach. start work on rmdir.
-rw-r--r--dbfs.c186
1 files changed, 128 insertions, 58 deletions
diff --git a/dbfs.c b/dbfs.c
index 2ac1cc3..40022fe 100644
--- a/dbfs.c
+++ b/dbfs.c
@@ -20,6 +20,12 @@ struct dbfs_inode {
struct dbfs_raw_inode raw_inode;
};
+struct dbfs_lookup_info {
+ const char *name;
+ size_t namelen;
+ guint64 *ino;
+};
+
static DB_ENV *env;
static DB *db_data;
static DB *db_meta;
@@ -98,6 +104,75 @@ static int dbfs_read_dir(guint64 ino, DBT *val)
return rc;
}
+typedef int (*dbfs_dir_actor_t) (struct dbfs_dirent *, void *);
+
+static int dbfs_dir_foreach(void *dir, dbfs_dir_actor_t func, void *userdata)
+{
+ struct dbfs_dirent *de;
+ void *p;
+ int rc = 0;
+
+ p = dir;
+ while (1) {
+ de = p;
+ de->magic = GUINT32_FROM_LE(de->magic);
+ de->namelen = GUINT16_FROM_LE(de->namelen);
+ de->ino = GUINT64_FROM_LE(de->ino);
+
+ g_assert (de->magic == DBFS_DE_MAGIC);
+ if (!de->namelen)
+ break;
+
+ rc = func(de, userdata);
+ if (rc)
+ break;
+
+ p += sizeof(struct dbfs_dirent) + de->namelen +
+ (4 - (de->namelen & 0x3));
+ }
+
+ return rc;
+}
+
+static int dbfs_dir_cmp(struct dbfs_dirent *de, void *userdata)
+{
+ struct dbfs_lookup_info *li = userdata;
+
+ if ((li->namelen == de->namelen) &&
+ (!memcmp(li->name, de->name, li->namelen))) {
+ *li->ino = de->ino;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int dbfs_lookup(guint64 parent, const char *name, guint64 *ino)
+{
+ struct dbfs_lookup_info li;
+ size_t namelen = strlen(name);
+ DBT val;
+ int rc;
+
+ *ino = 0;
+
+ rc = dbfs_read_dir(parent, &val);
+ if (rc)
+ return rc;
+
+ li.name = name;
+ li.namelen = namelen;
+ li.ino = ino;
+ rc = dbfs_dir_foreach(val.data, dbfs_dir_cmp, &li);
+ if (rc)
+ rc = 0;
+ else
+ rc = -ENOENT;
+
+ free(val.data);
+ return rc;
+}
+
static void dbfs_op_getattr(fuse_req_t req, fuse_ino_t ino_n,
struct fuse_file_info *fi)
{
@@ -133,52 +208,23 @@ static void dbfs_op_getattr(fuse_req_t req, fuse_ino_t ino_n,
static void dbfs_op_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
- struct dbfs_dirent *de;
- DBT val;
+ struct fuse_entry_param e;
+ guint64 ino;
int rc;
- void *p;
- size_t namelen = strlen(name);
- rc = dbfs_read_dir(parent, &val);
+ rc = dbfs_lookup(parent, name, &ino);
if (rc) {
fuse_reply_err(req, rc);
return;
}
- p = val.data;
- while (1) {
- de = p;
- de->magic = GUINT32_FROM_LE(de->magic);
- de->namelen = GUINT16_FROM_LE(de->namelen);
- de->ino = GUINT64_FROM_LE(de->ino);
-
- g_assert (de->magic == DBFS_DE_MAGIC);
- if (!de->namelen)
- break;
-
- if ((namelen == de->namelen) &&
- (!memcmp(name, de->name, namelen))) {
- struct fuse_entry_param e;
-
- memset(&e, 0, sizeof(e));
-
- e.ino = de->ino;
- e.attr_timeout = 1.0;
- e.entry_timeout = 1.0;
-
- fuse_reply_entry(req, &e);
-
- goto out;
- }
-
- p += sizeof(struct dbfs_dirent) + de->namelen +
- (4 - (de->namelen & 0x3));
- }
+ memset(&e, 0, sizeof(e));
- fuse_reply_err(req, ENOENT);
+ e.ino = ino;
+ e.attr_timeout = 2.0;
+ e.entry_timeout = 2.0;
-out:
- free(val.data);
+ fuse_reply_entry(req, &e);
}
static void dbfs_op_opendir(fuse_req_t req, fuse_ino_t ino,
@@ -233,37 +279,60 @@ static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
return fuse_reply_buf(req, NULL, 0);
}
+static int dbfs_fill_dirbuf(struct dbfs_dirent *de, void *userdata)
+{
+ struct dirbuf *b = userdata;
+ char *s = g_strndup(de->name, de->namelen);
+ dirbuf_add(b, s, de->ino);
+ free(s);
+ return 0;
+}
+
static void dbfs_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
struct dirbuf b;
- struct dbfs_dirent *de;
void *p;
- char *s;
+
+ p = (void *) (unsigned long) fi->fh;
memset(&b, 0, sizeof(b));
+ dbfs_dir_foreach(p, dbfs_fill_dirbuf, &b);
- p = (void *) (unsigned long) fi->fh;
- while (1) {
- de = p;
- de->magic = GUINT32_FROM_LE(de->magic);
- de->namelen = GUINT16_FROM_LE(de->namelen);
- de->ino = GUINT64_FROM_LE(de->ino);
+ reply_buf_limited(req, b.p, b.size, off, size);
+ free(b.p);
+}
- g_assert (de->magic == DBFS_DE_MAGIC);
- if (!de->namelen)
- break;
+static void dbfs_op_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
+{
+ struct dbfs_inode *ino;
+ guint64 ino_n;
+ int rc;
+ DBT val;
- s = g_strndup(de->name, de->namelen);
- dirbuf_add(&b, s, de->ino);
- free(s);
+ rc = dbfs_lookup(parent, name, &ino_n);
+ if (rc) {
+ fuse_reply_err(req, rc);
+ return;
+ }
- p += sizeof(struct dbfs_dirent) + de->namelen +
- (4 - (de->namelen & 0x3));
+ rc = dbfs_read_inode(ino_n, &ino);
+ if (rc) {
+ fuse_reply_err(req, rc);
+ return;
+ }
+ if (!S_ISDIR(ino->raw_inode.mode)) {
+ g_free(ino);
+ fuse_reply_err(req, ENOTDIR);
+ return;
}
- reply_buf_limited(req, b.p, b.size, off, size);
- free(b.p);
+ rc = dbfs_read_dir(parent, &val);
+ if (rc) {
+ g_free(ino);
+ fuse_reply_err(req, rc);
+ return;
+ }
}
static void hello_ll_open(fuse_req_t req, fuse_ino_t ino,
@@ -286,9 +355,10 @@ static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
reply_buf_limited(req, hello_str, strlen(hello_str), off, size);
}
-static struct fuse_lowlevel_ops hello_ll_oper = {
+static struct fuse_lowlevel_ops dbfs_ops = {
.lookup = dbfs_op_lookup,
.getattr = dbfs_op_getattr,
+ .rmdir = dbfs_op_rmdir,
.open = hello_ll_open,
.read = hello_ll_read,
.opendir = dbfs_op_opendir,
@@ -310,8 +380,8 @@ int main(int argc, char *argv[])
(fd = fuse_mount(mountpoint, &args)) != -1) {
struct fuse_session *se;
- se = fuse_lowlevel_new(&args, &hello_ll_oper,
- sizeof(hello_ll_oper), NULL);
+ se = fuse_lowlevel_new(&args, &dbfs_ops,
+ sizeof(dbfs_ops), NULL);
if (se != NULL) {
if (fuse_set_signal_handlers(se) != -1) {
struct fuse_chan *ch = fuse_kern_chan_new(fd);