[Top][All Lists]
[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:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r5149 - gnunet-fuse,
gnunet <=