gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r5149 - gnunet-fuse


From: gnunet
Subject: [GNUnet-SVN] r5149 - gnunet-fuse
Date: Mon, 25 Jun 2007 23:11:53 -0600 (MDT)

Author: amatus
Date: 2007-06-25 23:11:52 -0600 (Mon, 25 Jun 2007)
New Revision: 5149

Modified:
   gnunet-fuse/README
   gnunet-fuse/directory.c
   gnunet-fuse/dirent.c
   gnunet-fuse/getattr.c
   gnunet-fuse/gnfs.h
   gnunet-fuse/main.c
   gnunet-fuse/open.c
   gnunet-fuse/read.c
   gnunet-fuse/readdir.c
   gnunet-fuse/special_file.c
Log:
Beginnings of write support

Modified: gnunet-fuse/README
===================================================================
--- gnunet-fuse/README  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/README  2007-06-26 05:11:52 UTC (rev 5149)
@@ -1,28 +1,26 @@
                     gnunet-fuse - FUSE filesystem for GNUnet
 
-NOTE: Currently only read-only mounting is supported.
-
 Summary
 =======
 You need the URI of a file with the mime-type of application/gnunet-directory.
 You can either publish a directory with gnunet-insert or do a search for the
 mime-type. To mount the URI use the following command.
 
-$ gnunet-fs gnunet://ecrs/chk/XXXX/YYYY.NNNN /mnt
+$ echo gnunet://ecrs/chk/XXXX/YYYY.NNNN > uri_file
+$ gnunet-fs uri_file /mnt
 
 Where gnunet://ecrs/chk/XXXX/YYYY.NNNN is the URI and /mnt is the mount point.
-I suggest you store your URIs one each to a file and use `cat uri` in place of
-the URI in the example above.
 
 Usage
 =====
-gnunet-fuse [OPTIONS] <URI> <PATH>
+gnunet-fuse [OPTIONS] <URI FILE> <PATH>
 Arguments mandatory for long options are also mandatory for short options.
   -h, --help                 print this help
   -c, --config=FILENAME      use configuration file FILENAME
   -L, --log=LOGLEVEL         configure logging to use LOGLEVEL
   -l, --logfile=FILE         set logfile name
   -a, --anonymity=LEVEL      set the desired LEVEL of sender-anonymity
+  -p, --priority=LEVEL       set the desired LEVEL of priority
   -u, --uri-files            Make .uri files visible
   -x, --Xfuse                Escape fuse option
 

Modified: gnunet-fuse/directory.c
===================================================================
--- gnunet-fuse/directory.c     2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/directory.c     2007-06-26 05:11:52 UTC (rev 5149)
@@ -59,9 +59,11 @@
        size_t len, rlen;
        int ret;
 
+       (void)key;
+
        if(isRoot == YES)
-               return d->cb(d->de, NULL, fi, key, isRoot, d->data);
-       
+               return OK;
+
        /* Figure out the filename and type from metadata */
        filename = ECRS_getFromMetaData(fi->meta, EXTRACTOR_FILENAME);
        if(filename == NULL)
@@ -79,7 +81,7 @@
        }
        else
                type = DE_FILE;
-       
+
        /* Create newpath, the path to this entry */
        rlen = strlen(d->de->de_path);
        newpath = MALLOC(rlen + len + 1);
@@ -89,13 +91,13 @@
        strcat(newpath, filename);
 
        /* Create a new dirent for this entry */
-       de = gn_dirent_new(newpath, fi->uri, type);
+       de = gn_dirent_new(newpath, fi->uri, fi->meta, type);
 
        /* Add it to the cache */
        gn_dirent_cache(de);
 
        /* Call the callback function */
-       ret = d->cb(de, filename, fi, key, isRoot, d->data);
+       ret = d->cb(de, filename, d->data);
 
        /* Clean up */
        gn_dirent_put(de);
@@ -104,6 +106,21 @@
        return ret;
 }
 
+static gboolean hash_foreach_cb(gpointer key, gpointer value, gpointer data)
+{
+       struct dir_for_each_data *d = data;
+       struct dirent *de = value;
+       char *filename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+       int ret;
+
+       (void)key;
+
+       gn_dirent_ref(de);
+       ret = d->cb(de, filename, d->data);
+       gn_dirent_put(de);
+       return ret == SYSERR;
+}
+
 int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
        void *data)
 {
@@ -113,22 +130,86 @@
        int ret;
        guint64 len;
 
-       len = ECRS_fileSize(de->de_uri);
+       if(de->de_type != DE_DIR)
+               return -1;
+       d.cb = cb;
+       d.data = data;
+       d.de = de;
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               return -1;
+       if(de->de_dirty)
+       {
+               g_hash_table_find(de->de_dir, hash_foreach_cb, &d);
+               SEMAPHORE_UP(de->de_file_sema);
+               return 0;
+       }
+       len = ECRS_fileSize(de->de_fi.uri);
        mem = MALLOC(len);
-       ret = ECRS_downloadPartialFile(ectx, cfg, de->de_uri, "/dev/null",
+       ret = ECRS_downloadPartialFile(ectx, cfg, de->de_fi.uri, "/dev/null",
                anonymity, 0, len, YES, dpcb, mem, tt, NULL);
+       SEMAPHORE_UP(de->de_file_sema);
        if(ret != OK)
        {
                GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
                        "%s: failed to download directory\n", __FUNCTION__);
-               goto err_out;
+               ret = -1;
+               goto out;
        }
-       d.cb = cb;
-       d.data = data;
-       d.de = de;
        ECRS_listDirectory(ectx, mem, len, &md, dir_for_each_cb, &d);
-       return 0;
-err_out:
+       ECRS_freeMetaData(md);
+       ret = 0;
+out:
        FREE(mem);
-       return -1;
+       return ret;
 }
+
+static int directory_insert_callback(struct dirent *de, const gchar *filename,
+       void *data)
+{
+       struct dir_for_each_data *d = data;
+
+       (void)filename;
+       gn_dirent_ref(de);
+       g_hash_table_replace(d->de->de_dir, de->de_path, de);
+       return OK;
+}
+
+int gn_directory_insert(struct dirent *de_dir, struct dirent *de_new)
+{
+       struct dir_for_each_data d;
+       void *mem;
+       guint64 len;
+       int ret = 0;
+       struct ECRS_MetaData *md;
+
+       if(SEMAPHORE_DOWN(de_dir->de_file_sema, YES) == SYSERR)
+               return -1;
+       if(!de_dir->de_dirty)
+       {
+               de_dir->de_dirty = 1;
+               de_dir->de_dir = g_hash_table_new_full(g_str_hash, g_str_equal,
+                       NULL, (GDestroyNotify)gn_dirent_put);
+               d.cb = directory_insert_callback;
+               d.de = de_dir;
+               len = ECRS_fileSize(de_dir->de_fi.uri);
+               mem = MALLOC(len);
+               ret = ECRS_downloadPartialFile(ectx, cfg, de_dir->de_fi.uri,
+                       "/dev/null", anonymity, 0, len, YES, dpcb, mem, tt,
+                       NULL);
+               if(ret != OK)
+               {
+                       GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
+                               "%s: failed to download directory\n",
+                               __FUNCTION__);
+                       ret = -1;
+                       goto out;
+               }
+               ECRS_listDirectory(ectx, mem, len, &md, dir_for_each_cb, &d);
+               ECRS_freeMetaData(md);
+       }
+       gn_dirent_ref(de_new);
+       g_hash_table_replace(de_dir->de_dir, de_new->de_path, de_new);
+out:
+       SEMAPHORE_UP(de_dir->de_file_sema);
+       return ret;
+}

Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c        2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/dirent.c        2007-06-26 05:11:52 UTC (rev 5149)
@@ -18,27 +18,22 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <unistd.h>
 #include <glib.h>
 #include <string.h>
 #include "gnfs.h"
 
 GHashTable *path_hash;
-struct MUTEX *path_mutex;
+struct SEMAPHORE *path_sema;
 
 /*
- * Create a new dirent with a reference, path and uri are copied
+ * Reference a dirent, call gn_dirent_put when finished
  */
-struct dirent *gn_dirent_new(const gchar *path, struct ECRS_URI *uri,
-       gchar type)
+void gn_dirent_ref(struct dirent *de)
 {
-       struct dirent *de;
-
-       de = MALLOC(sizeof(*de));
-       de->de_path = STRDUP(path);
-       de->de_uri = ECRS_dupUri(uri);
-       de->de_type = type;
-       de->de_refs = 1;
-       return de;
+       MUTEX_LOCK(de->de_mutex);
+       de->de_refs++;
+       MUTEX_UNLOCK(de->de_mutex);
 }
 
 /*
@@ -48,52 +43,96 @@
 {
        struct dirent *de;
 
-       MUTEX_LOCK(path_mutex);
+       if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
+               return NULL;
        de = g_hash_table_lookup(path_hash, path);
        if(de != NULL)
-               de->de_refs++;
-       MUTEX_UNLOCK(path_mutex);
+               gn_dirent_ref(de);
+       SEMAPHORE_UP(path_sema);
        return de;
 }
 
 /*
- * Reference a dirent, call gn_dirent_put when finished
+ * Release a reference to a dirent
  */
-void gn_dirent_ref(struct dirent *de)
+void gn_dirent_put(struct dirent *de)
 {
-       MUTEX_LOCK(path_mutex);
-       de->de_refs++;
-       MUTEX_UNLOCK(path_mutex);
-}
-
-static void dirent_destroy(gpointer data)
-{
-       struct dirent *de = data;
-
+       MUTEX_LOCK(de->de_mutex);
        de->de_refs--;
        if(de->de_refs < 1)
        {
+               MUTEX_UNLOCK(de->de_mutex);
+               MUTEX_DESTROY(de->de_mutex);
                FREE(de->de_path);
-               ECRS_freeUri(de->de_uri);
+               SEMAPHORE_DESTROY(de->de_file_sema);
+               if(de->de_fi.uri != NULL)
+                       ECRS_freeUri(de->de_fi.uri);
+               if(de->de_fi.meta != NULL)
+                       ECRS_freeMetaData(de->de_fi.meta);
+               if(de->de_dirty)
+               {
+                       if(de->de_type == DE_FILE)
+                       {
+                               close(de->de_fd);
+                               unlink(de->de_filename);
+                               FREE(de->de_filename);
+                       }
+                       else
+                       {
+                               g_hash_table_destroy(de->de_dir);
+                       }
+               }
                FREE(de);
+               return;
        }
+       MUTEX_UNLOCK(de->de_mutex);
 }
 
+void gn_dirent_cache_init(void)
+{
+       path_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+               (GDestroyNotify)gn_dirent_put);
+       path_sema = SEMAPHORE_CREATE(1);
+}
+
 /*
- * Release a reference to a dirent
+ * Create a new dirent with a reference, path and uri are copied
  */
-void gn_dirent_put(struct dirent *de)
+struct dirent *gn_dirent_new(const gchar *path, struct ECRS_URI *uri,
+       struct ECRS_MetaData *meta, gchar type)
 {
-       MUTEX_LOCK(path_mutex);
-       dirent_destroy(de);
-       MUTEX_UNLOCK(path_mutex);
-}
+       struct dirent *de;
 
-void gn_dirent_cache_init(void)
-{
-       path_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-               dirent_destroy);
-       path_mutex = MUTEX_CREATE(0);
+       de = MALLOC(sizeof(*de));
+       de->de_path = STRDUP(path);
+       de->de_mutex = MUTEX_CREATE(0);
+       de->de_refs = 1;
+       de->de_type = type;
+       de->de_file_sema = SEMAPHORE_CREATE(1);
+       if(uri != NULL)
+       {
+               de->de_fi.uri = ECRS_dupUri(uri);
+               de->de_dirty = 0;
+       }
+       else
+       {
+               de->de_dirty = 1;
+               if(type == DE_FILE)
+               {
+                       char filename[] = "/tmp/gnfsXXXXXX";
+
+                       de->de_fd = mkstemp(filename);
+                       de->de_filename = STRDUP(filename);
+               }
+               else
+               {
+                       de->de_dir = g_hash_table_new_full(g_str_hash,
+                               g_str_equal, NULL,
+                               (GDestroyNotify)gn_dirent_put);
+               }
+       }
+       de->de_fi.meta = ECRS_dupMetaData(meta);
+       return de;
 }
 
 /*
@@ -101,18 +140,15 @@
  */
 void gn_dirent_cache(struct dirent *de)
 {
-       gchar *uristr;
-
-       uristr = ECRS_uriToString(de->de_uri);
        GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: name '%s' uri '%s'\n", __FUNCTION__, de->de_path, uristr);
-       FREE(uristr);
+               "%s: path '%s'\n", __FUNCTION__, de->de_path);
        /* TODO: Here we need to see if the cache has gotten too big and empty
         * it */
-       MUTEX_LOCK(path_mutex);
-       de->de_refs++;
+       gn_dirent_ref(de);
+       if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
+               return;
        g_hash_table_replace(path_hash, de->de_path, de);
-       MUTEX_UNLOCK(path_mutex);
+       SEMAPHORE_UP(path_sema);
 }
 
 struct dirent_find_data
@@ -123,14 +159,11 @@
 };
 
 static gboolean dirent_find(struct dirent *de, const gchar *filename,
-       const ECRS_FileInfo *fi, const HashCode512 *key, int isRoot, void *data)
+       void *data)
 {
        struct dirent_find_data *dfd = data;
 
-       (void)fi;
-       (void)key;
-
-       if(isRoot == YES || dfd->found == 1 || strcmp(filename, dfd->name) != 0)
+       if(dfd->found == 1 || strcmp(filename, dfd->name) != 0)
                return OK;
 
        dfd->found = 1;
@@ -150,12 +183,10 @@
        struct dirent_find_data dfd;
 
        /* Start de off at the root */
-       MUTEX_LOCK(root_mutex);
        de = root_de;
        gn_dirent_ref(de);
-       MUTEX_UNLOCK(root_mutex);
 
-       /* Root shortcut before we grab path_mutex */
+       /* Root shortcut */
        if(strcmp(path, G_DIR_SEPARATOR_S) == 0)
                return de;
 
@@ -226,3 +257,112 @@
 
        return de;
 }
+
+struct upload_data
+{
+       int count;
+       ECRS_FileInfo *fis;
+};
+
+int dirent_upload_locked(struct dirent *de);
+
+void upload_foreach(gpointer key, gpointer value, gpointer data)
+{
+       struct dirent *de = value;
+       struct upload_data *d = data;
+
+       (void)key;
+
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               return;
+       if(de->de_dirty)
+       {
+               if(de->de_type == DE_FILE)
+               {
+                       if(de->de_fi.uri == NULL)
+                               goto out;
+               }
+               else
+               {
+                       dirent_upload_locked(de);
+               }
+       }
+       d->count++;
+       d->fis = REALLOC(d->fis, d->count * sizeof(*d->fis));
+       d->fis[d->count - 1].uri = ECRS_dupUri(de->de_fi.uri);
+       d->fis[d->count - 1].meta = ECRS_dupMetaData(de->de_fi.meta);
+out:
+       SEMAPHORE_UP(de->de_file_sema);
+}
+
+void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
+       void *closure)
+{
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       (void)closure;
+}
+
+int tt(void *closure)
+{
+       (void)closure;
+
+       return fuse_interrupted() ? SYSERR : OK;
+}
+
+int dirent_upload_locked(struct dirent *de)
+{
+       int i, fd;
+       struct upload_data d;
+       char *buf, filename[] = "/tmp/gnfsXXXXXX";
+       guint64 len;
+       struct ECRS_URI *uri;
+
+       if(!de->de_dirty)
+               return 0;
+       d.count = 0;
+       d.fis = NULL;
+       g_hash_table_foreach(de->de_dir, upload_foreach, &d);
+       if(ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
+               de->de_fi.meta) == SYSERR)
+               goto out;
+       fd = mkstemp(filename);
+       if(fd == -1)
+               goto out;
+       write(fd, buf, len);
+       close(fd);
+       if(ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
+               -1, upcb, NULL, tt, NULL, &uri) == SYSERR)
+               goto out_unlink_file;
+       if(de->de_fi.uri != NULL)
+               ECRS_freeUri(de->de_fi.uri);
+       de->de_fi.uri = uri;
+       g_hash_table_destroy(de->de_dir);
+       de->de_dirty = 0;
+out_unlink_file:
+       unlink(filename);
+out:
+       for(i = 0; i < d.count; i++)
+       {
+               ECRS_freeUri(d.fis[i].uri);
+               ECRS_freeMetaData(d.fis[i].meta);
+       }
+       FREE(d.fis);
+       return 0;
+}
+
+/*
+ * Make a dirty dirent clean - it should be a good tradeoff to only upload
+ * changes to directories here and upload changes to files on release
+ */
+int gn_dirent_upload(struct dirent *de)
+{
+       int ret;
+
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               return -1;
+       ret = dirent_upload_locked(de);
+       SEMAPHORE_UP(de->de_file_sema);
+       return ret;
+}

Modified: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c       2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/getattr.c       2007-06-26 05:11:52 UTC (rev 5149)
@@ -28,33 +28,55 @@
 int gn_getattr(const char *path, struct stat *stbuf)
 {
        struct dirent *de;
-       char *special;
+       guint64 size = 0;
 
        GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "getattr for '%s'\n",
                path);
 
        /* Check to see if this is a special file */
-       special = gn_get_special_file(path);
-       if(special != NULL)
+       if(gn_exists_special_file(path))
        {
                memset(stbuf, 0, sizeof(*stbuf));
                stbuf->st_mode = 0555 | S_IFREG;
                stbuf->st_nlink = 1;
-               stbuf->st_size = strlen(special);
-               FREE(special);
+               stbuf->st_size = 0;
                return 0;
        }
 
        /* Fill in dirent stat info */
        de = gn_dirent_find(path);
        if(de == NULL)
+       {
+               GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
+                       "%s: could not find path '%s'\n", __FUNCTION__, path);
                return -ENOENT;
+       }
 
        memset(stbuf, 0, sizeof(*stbuf));
-       stbuf->st_mode = 0555;
+       stbuf->st_mode = 0777;
        stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
        stbuf->st_nlink = 1;
-       stbuf->st_size = ECRS_fileSize(de->de_uri);
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               return -ENOENT;
+       if(de->de_dirty)
+       {
+               if(de->de_type == DE_FILE && disk_file_size(ectx,
+                       de->de_filename, &size, NO) == SYSERR)
+               {
+                       GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
+                               "%s: disk_file_size failed for '%s'\n",
+                               __FUNCTION__, de->de_filename);
+                       SEMAPHORE_UP(de->de_file_sema);
+                       gn_dirent_put(de);
+                       return -ENOENT;
+               }
+       }
+       else
+       {
+               size = ECRS_fileSize(de->de_fi.uri);
+       }
+       SEMAPHORE_UP(de->de_file_sema);
        gn_dirent_put(de);
+       stbuf->st_size = size;
        return 0;
 }

Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/gnfs.h  2007-06-26 05:11:52 UTC (rev 5149)
@@ -38,27 +38,43 @@
 struct dirent
 {
        gchar *de_path;
-       struct ECRS_URI *de_uri;
+       struct MUTEX *de_mutex;
+       gint de_refs;
        gchar de_type;
 #define DE_FILE        'f'
 #define DE_DIR 'd'
-       gint de_refs;
+       /* Access of anything below this must lock de_file_sema */
+       struct SEMAPHORE *de_file_sema;
+       gboolean de_dirty;
+       /* de_fi.uri is valid only if de_dirty is not set */
+       ECRS_FileInfo de_fi;
+       /* This is valid only if de_dirty is set */
+       union
+       {
+               /* For directories */
+               GHashTable *de_dir;
+               /* For files */
+               struct
+               {
+                       gint de_fd;
+                       gchar *de_filename;
+               };
+       };
 };
 
 typedef int (*gn_dir_for_each_callback)(struct dirent *de,
-       const gchar *filename, const ECRS_FileInfo *fi, const HashCode512 *key,
-       int isRoot, void *data);
+       const gchar *filename, void *data);
 
 extern struct GC_Configuration *cfg;
 extern struct GE_Context *ectx;
 extern unsigned int anonymity;
+extern unsigned int priority;
 extern int uri_files;
 extern struct dirent *root_de;
-extern struct MUTEX *root_mutex;
 
 /* dirent.c */
 struct dirent *gn_dirent_new(const gchar *path, struct ECRS_URI *uri,
-       gchar type);
+       struct ECRS_MetaData *meta, gchar type);
 struct dirent *gn_dirent_get(const gchar *path);
 void gn_dirent_ref(struct dirent *de);
 void gn_dirent_put(struct dirent *de);
@@ -69,6 +85,7 @@
 /* directory.c */
 int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
         void *data);
+int gn_directory_insert(struct dirent *de_dir, struct dirent *de_new);
 
 /* FUSE function files */
 int gn_getattr(const char *path, struct stat *stbuf);
@@ -79,6 +96,7 @@
        struct fuse_file_info *fi);
 
 /* special_file.c */
+int gn_exists_special_file(const char *path);
 char *gn_get_special_file(const char *path);
 
 #endif /* _GNFS_H_ */

Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/main.c  2007-06-26 05:11:52 UTC (rev 5149)
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 #include <glib.h>
 #include <fuse.h>
 #include <GNUnet/gnunet_directories.h>
@@ -33,14 +34,23 @@
 struct GE_Context *ectx;
 static char *cfgFilename = DEFAULT_CLIENT_CONFIG_FILE;
 static char *cfgLogfile = "/tmp/gnunet_fuse.log";
+
+/* Level of anonymity for downloading and uploading files */
 unsigned int anonymity = 1;
+
+/* Priority for uploaded files */
+unsigned int priority = 1000;
+
+/* Flag for including .uri files in readdir() */
 int uri_files = 0;
+
+/* argv and argc to pass to fuse, filled in by main and getopt_configure_argv 
*/
 char **fuse_argv;
 int fuse_argc;
 
 /* Root directory entry, currently used by the dirent cache when asked for / */
+int root_fd;
 struct dirent *root_de;
-struct MUTEX *root_mutex;
 
 int getopt_configure_argv(CommandLineProcessorContext *ctx, void *scls,
        const char *cmdLineOption, const char *value)
@@ -74,6 +84,9 @@
        { 'a', "anonymity", "LEVEL",
                "set the desired LEVEL of sender-anonymity", 1,
                &gnunet_getopt_configure_set_uint, &anonymity },
+       { 'p', "priority", "LEVEL",
+               "set the desired LEVEL of priority", 1,
+               &gnunet_getopt_configure_set_uint, &priority },
        { 'u', "uri-files", NULL, "Make .uri files visible", 0,
                &gnunet_getopt_configure_set_one, &uri_files },
        { 'x', "Xfuse", NULL, "Escape fuse option", 1,
@@ -85,17 +98,17 @@
 {
        int i, ret;
        struct ECRS_URI *uri;
+       char *buf;
 
-       /* Initialize fuse options to specify a read-only filesystem (for now)*/
-       fuse_argc = 3;
+       /* Initialize fuse options */
+       fuse_argc = 1;
        fuse_argv = MALLOC(sizeof(char *) * (fuse_argc + 1));
        fuse_argv[0] = argv[0];
-       fuse_argv[1] = "-o";
-       fuse_argv[2] = "ro";
-       fuse_argv[3] = NULL;
+       fuse_argv[1] = NULL;
 
        /* Parse gnunet options */
-       i = GNUNET_init(argc, argv, "gnunet-fuse [OPTIONS] <URI> <PATH>",
+       i = GNUNET_init(argc, argv,
+               "gnunet-fuse [OPTIONS] <URI FILE> <MOUNT-POINT>",
                &cfgFilename, gn_options, &ectx, &cfg);
        if(i == -1)
        {
@@ -117,17 +130,67 @@
        }
 
        /* Set URI as our root directory entry */
-       uri = ECRS_stringToUri(ectx, argv[i]);
-       if(uri == NULL || !ECRS_isFileUri(uri))
+       gn_dirent_cache_init();
+       if(disk_file_test(ectx, argv[i]) == YES)
        {
-               printf("URI '%s' cannot be mounted\n", argv[i]);
-               ret = -1;
-               goto quit;
+               guint64 len;
+               char *uribuf;
+
+               root_fd = disk_file_open(ectx, argv[i], O_RDWR | O_SYNC);
+               if(root_fd == -1)
+               {
+                       printf("Unable to open URI file: %s\n", argv[i]);
+                       ret = -1;
+                       goto quit;
+               }
+               if(disk_file_size(ectx, argv[i], &len, YES) == SYSERR)
+               {
+                       printf("Unable to determine URI file size\n");
+                       ret = -1;
+                       goto out_close_root;
+               }
+               uribuf = MALLOC(len + 1);
+               read(root_fd, uribuf, len);
+               uribuf[len] = '\0';
+               uri = ECRS_stringToUri(ectx, uribuf);
+               FREE(uribuf);
+               if(uri == NULL)
+               {
+                       printf("URI cannot be parsed\n");
+                       ret = -1;
+                       goto out_close_root;
+               }
+               if(!ECRS_isFileUri(uri))
+               {
+                       struct ECRS_URI *new_uri;
+
+                       new_uri = ECRS_getContentUri(uri);
+                       if(new_uri == NULL)
+                       {
+                               printf("URI cannot be mounted\n");
+                               ret = -1;
+                               goto out_close_root;
+                       }
+                       ECRS_freeUri(uri);
+                       uri = new_uri;
+               }
+               root_de = gn_dirent_new(G_DIR_SEPARATOR_S, uri, NULL, DE_DIR);
+               ECRS_freeUri(uri);
        }
-       gn_dirent_cache_init();
-       root_de = gn_dirent_new(G_DIR_SEPARATOR_S, uri, DE_DIR);
-       ECRS_freeUri(uri);
-       root_mutex = MUTEX_CREATE(0);
+       else
+       {
+               /* In the case where the file does not exist, let's mount an
+                * empty directory and create the file to store its URI */
+               root_fd = disk_file_open(ectx, argv[i], O_RDWR | O_SYNC
+                       | O_CREAT, 0666);
+               if(root_fd == -1)
+               {
+                       printf("Unable to create URI file: %s\n", argv[i]);
+                       ret = -1;
+                       goto quit;
+               }
+               root_de = gn_dirent_new(G_DIR_SEPARATOR_S, NULL, NULL, DE_DIR);
+       }
 
        /* Add mount point as the last fuse option */
        fuse_argv = REALLOC(fuse_argv, sizeof(char *) * (fuse_argc + 2));
@@ -137,6 +200,15 @@
 
        GE_LOG(ectx, GE_BULK | GE_USER | GE_DEBUG, "calling fuse_main\n");
        ret = fuse_main(fuse_argc, fuse_argv, &fops, NULL);
+       GE_LOG(ectx, GE_BULK | GE_USER | GE_DEBUG, "fuse_main returned\n");
+
+       /* Save root uri */
+       buf = gn_get_special_file(G_DIR_SEPARATOR_S URI_FILE);
+       ftruncate(root_fd, 0);
+       write(root_fd, buf, strlen(buf));
+       FREE(buf);
+out_close_root:
+       disk_file_close(ectx, argv[i], root_fd);
 quit:
        FREE(fuse_argv);
        GNUNET_fini(ectx, cfg);

Modified: gnunet-fuse/open.c
===================================================================
--- gnunet-fuse/open.c  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/open.c  2007-06-26 05:11:52 UTC (rev 5149)
@@ -27,31 +27,26 @@
 int gn_open(const char *path, struct fuse_file_info *fi)
 {
        struct dirent *de;
-       char *special;
 
        (void)fi;
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "open for '%s'\n",
-               path);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
        
        /* Check for special file */
-       special = gn_get_special_file(path);
-       if(special != NULL)
-       {
-               FREE(special);
+       if(gn_exists_special_file(path))
                return 0;
-       }
 
        de = gn_dirent_find(path);
        if(de == NULL)
        {
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "open: file not found\n");
+                       "%s: file not found\n", __FUNCTION__);
                return -ENOENT;
        }
        if(de->de_type != DE_FILE)
        {
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "open: not a file\n");
+                       "%s: not a file\n", __FUNCTION__);
                gn_dirent_put(de);
                return -ENOENT;
        }

Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/read.c  2007-06-26 05:11:52 UTC (rev 5149)
@@ -18,10 +18,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <fuse.h>
+#define _XOPEN_SOURCE 500
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <fuse.h>
 #include "gnfs.h"
 
 struct read_data
@@ -75,7 +76,8 @@
        struct dirent *de;
        struct read_data d;
        char *special;
-       int ret, slen;
+       int ret;
+       ssize_t slen;
        guint64 len;
 
        (void)fi;
@@ -117,11 +119,25 @@
                size = -ENOENT;
                goto out;
        }
-       len = ECRS_fileSize(de->de_uri);
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+       {
+               size = -EINTR;
+               goto out;
+       }
+       if(de->de_dirty)
+       {
+               slen = pread(de->de_fd, buf, size, offset);
+               if(slen == -1)
+                       size = -errno;
+               else
+                       size = slen;
+               goto out_sema_up;
+       }
+       len = ECRS_fileSize(de->de_fi.uri);
        if((guint64)offset >= len)
        {
                size = 0;
-               goto out;
+               goto out_sema_up;
        }
        if((guint64)offset + size > len)
        {
@@ -130,7 +146,7 @@
        d.buf = buf;
        d.size = size;
        d.offset = offset;
-       ret = ECRS_downloadPartialFile(ectx, cfg, de->de_uri, "/dev/null",
+       ret = ECRS_downloadPartialFile(ectx, cfg, de->de_fi.uri, "/dev/null",
                anonymity, offset, size, YES, dpcb, &d, tt, NULL);
        if(ret != OK)
        {
@@ -138,6 +154,8 @@
                        "%s: failed to download directory\n", __FUNCTION__);
                size = -ENODATA;
        }
+out_sema_up:
+       SEMAPHORE_UP(de->de_file_sema);
 out:
        gn_dirent_put(de);
        return size;

Modified: gnunet-fuse/readdir.c
===================================================================
--- gnunet-fuse/readdir.c       2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/readdir.c       2007-06-26 05:11:52 UTC (rev 5149)
@@ -38,17 +38,12 @@
 };
 
 static int readdir_callback(struct dirent *de, const gchar *filename,
-       const ECRS_FileInfo *fi, const HashCode512 *key, int isRoot, void *data)
+       void *data)
 {
        struct readdir_callback_data *d = data;
 
        (void)de;
-       (void)fi;
-       (void)key;
 
-       if(isRoot)
-               return OK;
-
        if(d->prefix != NULL)
        {
                char *buf = MALLOC(strlen(d->prefix) + strlen(filename) + 1);

Modified: gnunet-fuse/special_file.c
===================================================================
--- gnunet-fuse/special_file.c  2007-06-26 03:10:38 UTC (rev 5148)
+++ gnunet-fuse/special_file.c  2007-06-26 05:11:52 UTC (rev 5149)
@@ -23,6 +23,49 @@
 #include <GNUnet/gnunet_ecrs_lib.h>
 #include "gnfs.h"
 
+/* Checks to see if path is the path to a special file */
+int gn_exists_special_file(const char *path)
+{
+       struct dirent *de;
+       char *file, *parent;
+       int ret = 0;
+
+       /* Break path into parent and file (dirname and basename kinda) */
+       parent = STRDUP(path);
+       file = strrchr(parent, G_DIR_SEPARATOR);
+       if(file == NULL)
+               goto out;
+       file[0] = '\0';
+       file++;
+
+       /* Check for special file name */
+       if(strcmp(file, URI_FILE) == 0)
+       {
+               ret = 1;
+       }
+       else if(strncmp(file, URI_FILE ".", URI_LEN + 1) == 0)
+       {
+               char *actual_file = MALLOC(strlen(path));
+
+               /* Return URI of the file named after the .uri. */
+               sprintf(actual_file, "%s" G_DIR_SEPARATOR_S "%s", parent,
+                       &file[URI_LEN + 1]);
+               de = gn_dirent_find(actual_file);
+               FREE(actual_file);
+               if(de == NULL)
+                       goto out;
+               gn_dirent_put(de);
+               ret = 1;
+       }
+out:
+       FREE(parent);
+       return ret;
+}
+
+/* 
+ * Returns a malloc'd string for a special file, and in the case of .uri files
+ * will sync it if it's dirty
+ */
 char *gn_get_special_file(const char *path)
 {
        struct dirent *de;
@@ -39,22 +82,31 @@
        /* Check for special file name */
        if(strcmp(file, URI_FILE) == 0)
        {
-               char *uri;
-
                /* Return URI of the 'current' directory */
                de = gn_dirent_find(parent);
                if(de == NULL)
                        goto out;
-               uri = ECRS_uriToString(de->de_uri);
+               if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               {
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               if(de->de_dirty)
+               {
+                       /* TODO: publish data here */
+                       SEMAPHORE_UP(de->de_file_sema);
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               buf = ECRS_uriToString(de->de_fi.uri);
+               SEMAPHORE_UP(de->de_file_sema);
                gn_dirent_put(de);
-               buf = MALLOC(strlen(uri) + 2);
-               strcpy(buf, uri);
-               FREE(uri);
+               buf = REALLOC(buf, strlen(buf) + 2);
                strcat(buf, "\n");
        }
        else if(strncmp(file, URI_FILE ".", URI_LEN + 1) == 0)
        {
-               char *uri, *actual_file = MALLOC(strlen(path));
+               char *actual_file = MALLOC(strlen(path));
 
                /* Return URI of the file named after the .uri. */
                sprintf(actual_file, "%s" G_DIR_SEPARATOR_S "%s", parent,
@@ -63,11 +115,22 @@
                FREE(actual_file);
                if(de == NULL)
                        goto out;
-               uri = ECRS_uriToString(de->de_uri);
+               if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+               {
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               if(de->de_dirty)
+               {
+                       /* TODO: publish data here */
+                       SEMAPHORE_UP(de->de_file_sema);
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               buf = ECRS_uriToString(de->de_fi.uri);
+               SEMAPHORE_UP(de->de_file_sema);
                gn_dirent_put(de);
-               buf = MALLOC(strlen(uri) + 2);
-               strcpy(buf, uri);
-               FREE(uri);
+               buf = REALLOC(buf, strlen(buf) + 2);
                strcat(buf, "\n");
        }
 out:





reply via email to

[Prev in Thread] Current Thread [Next in Thread]