[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r5302 - gnunet-fuse
From: |
gnunet |
Subject: |
[GNUnet-SVN] r5302 - gnunet-fuse |
Date: |
Thu, 12 Jul 2007 00:15:51 -0600 (MDT) |
Author: amatus
Date: 2007-07-12 00:15:47 -0600 (Thu, 12 Jul 2007)
New Revision: 5302
Added:
gnunet-fuse/release.c
Modified:
gnunet-fuse/ChangeLog
gnunet-fuse/Makefile.am
gnunet-fuse/configure.ac
gnunet-fuse/directory.c
gnunet-fuse/dirent.c
gnunet-fuse/getattr.c
gnunet-fuse/gnfs.h
gnunet-fuse/main.c
gnunet-fuse/mknod.c
gnunet-fuse/read.c
gnunet-fuse/readdir.c
gnunet-fuse/special_file.c
gnunet-fuse/write.c
Log:
Added support for creating modifying files
Modified: gnunet-fuse/ChangeLog
===================================================================
--- gnunet-fuse/ChangeLog 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/ChangeLog 2007-07-12 06:15:47 UTC (rev 5302)
@@ -1,4 +1,6 @@
-2007-06-18 David Barksdale <address@hidden> 0.7.2a
+2007-07-12 David Barksdale <address@hidden> 0.7.2-2
+* Added support for creating and modifying files
+2007-06-18 David Barksdale <address@hidden> 0.7.2-1
* Modified configure script to better detect compatability with GNUnet
2007-06-18 David Barksdale <address@hidden> 0.7.2
* Gratuitous version incrementation
Modified: gnunet-fuse/Makefile.am
===================================================================
--- gnunet-fuse/Makefile.am 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/Makefile.am 2007-07-12 06:15:47 UTC (rev 5302)
@@ -8,6 +8,7 @@
open.c \
read.c \
readdir.c \
+ release.c \
special_file.c \
write.c \
gnfs.h \
Modified: gnunet-fuse/configure.ac
===================================================================
--- gnunet-fuse/configure.ac 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/configure.ac 2007-07-12 06:15:47 UTC (rev 5302)
@@ -1,10 +1,11 @@
-AC_INIT(gnunet-fuse, 0.7.2a)
+AC_INIT(gnunet-fuse, 0.7.2)
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
AC_PROG_CC
AM_PROG_CC_C_O
-dnl AC_PROG_LIBTOOL
+AC_C_CHAR_UNSIGNED
+
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
PKG_CHECK_MODULES(GLIB, [glib-2.0])
@@ -12,7 +13,7 @@
# test for GNUnet core
gnunet=0
-AC_MSG_CHECKING(for GNUnet core)
+AC_MSG_CHECKING([for GNUnet core])
AC_ARG_WITH(gnunet,
[ --with-gnunet=PFX Base of GNUnet installation],
[AC_MSG_RESULT([$with_gnunet])
Modified: gnunet-fuse/directory.c
===================================================================
--- gnunet-fuse/directory.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/directory.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -40,24 +40,19 @@
static int tt(void *cls)
{
(void)cls;
- return fuse_interrupted() ? SYSERR : OK;
+ if(closing)
+ return OK;
+ if(fuse_interrupted())
+ return SYSERR;
+ return OK;
}
-struct dir_for_each_data
-{
- gn_dir_for_each_callback cb;
- void *data;
- struct dirent *de;
-};
-
-static int dir_for_each_cb(const ECRS_FileInfo *fi, const HashCode512 *key,
+static int dir_cache_cb(const ECRS_FileInfo *fi, const HashCode512 *key,
int isRoot, void *data)
{
- struct dir_for_each_data *d = data;
- struct dirent *de;
+ struct dirent *de, *deparent = data;
gchar *filename, *newpath, type;
size_t len, rlen;
- int ret;
(void)key;
@@ -83,133 +78,311 @@
type = DE_FILE;
/* Create newpath, the path to this entry */
- rlen = strlen(d->de->de_path);
+ rlen = strlen(deparent->de_path);
newpath = MALLOC(rlen + len + 1);
- strcpy(newpath, d->de->de_path);
- if(d->de->de_path[rlen - 1] != G_DIR_SEPARATOR)
+ strcpy(newpath, deparent->de_path);
+ if(deparent->de_path[rlen - 1] != G_DIR_SEPARATOR)
strcat(newpath, G_DIR_SEPARATOR_S);
strcat(newpath, filename);
- /* Create a new dirent for this entry */
- de = gn_dirent_new(newpath, fi->uri, fi->meta, type);
+ /* Create a new dirent for this entry only if one doesn't already exist
+ * and the only place that can be is in the cache */
+ de = gn_dirent_get(newpath);
+ if(de == NULL)
+ {
+ de = gn_dirent_new(newpath, fi->uri, fi->meta, type);
- /* Add it to the cache */
- gn_dirent_cache(de);
+ /* Add it to the cache (creates its own ref)*/
+ /* NB: the lock on deparent is enough to guarantee that another
+ * thread hasn't added this dirent to the cache in the time
+ * between the above check and this insert */
+ gn_dirent_cache(de);
+ }
- /* Call the callback function */
- ret = d->cb(de, filename, d->data);
+ /* Add it to the directory's list (steals our ref)*/
+ GE_ASSERT(ectx,
+ !g_hash_table_lookup(deparent->de_dir_hash, de->de_basename));
+ g_hash_table_replace(deparent->de_dir_hash, de->de_basename, de);
/* Clean up */
- gn_dirent_put(de);
FREE(filename);
FREE(newpath);
- return ret;
+ return OK;
}
-static gboolean hash_foreach_cb(gpointer key, gpointer value, gpointer data)
+static int directory_cache_locked(struct dirent *de)
{
- struct dir_for_each_data *d = data;
- struct dirent *de = value;
- char *filename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+ struct ECRS_MetaData *md;
+ void *mem;
int ret;
+ guint64 len;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+ __FUNCTION__, de->de_path);
+ len = ECRS_fileSize(de->de_fi.uri);
+ mem = MALLOC(len);
+ ret = ECRS_downloadPartialFile(ectx, cfg, de->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__);
+ FREE(mem);
+ return -1;
+ }
+ de->de_dir_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify)gn_dirent_put);
+ ECRS_listDirectory(ectx, mem, len, &md, dir_cache_cb, de);
+ FREE(mem);
+ ECRS_freeMetaData(md);
+ de->de_cached = 1;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: cached %d entries\n", __FUNCTION__,
+ g_hash_table_size(de->de_dir_hash));
+ return 0;
+}
+
+struct dir_foreach_data
+{
+ gn_dir_foreach_callback cb;
+ void *data;
+};
+
+static gboolean dir_foreach_callback(gpointer key, gpointer value,
+ gpointer data)
+{
+ struct dirent *de = value;
+ struct dir_foreach_data *d = data;
+
(void)key;
-
- gn_dirent_ref(de);
- ret = d->cb(de, filename, d->data);
- gn_dirent_put(de);
- return ret == SYSERR;
+ return d->cb(de, d->data) == -1;
}
-int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
+/*
+ * Call cb for each element in a directory
+ */
+int gn_directory_foreach(struct dirent *de, gn_dir_foreach_callback cb,
void *data)
{
- struct ECRS_MetaData *md;
- struct dir_for_each_data d;
- void *mem;
- int ret;
- guint64 len;
+ struct dir_foreach_data d;
+ int ret = 0;
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)
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
return -1;
- if(de->de_dirty)
+ if(!de->de_cached)
{
- g_hash_table_find(de->de_dir, hash_foreach_cb, &d);
- SEMAPHORE_UP(de->de_file_sema);
- return 0;
+ ret = directory_cache_locked(de);
+ if(ret == -1)
+ goto out;
}
- len = ECRS_fileSize(de->de_fi.uri);
- mem = MALLOC(len);
- 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)
+ d.cb = cb;
+ d.data = data;
+ g_hash_table_find(de->de_dir_hash, dir_foreach_callback, &d);
+out:
+ SEMAPHORE_UP(de->de_sema);
+ return ret;
+}
+
+/*
+ * Finds 'filename' in directory 'de' and returns a reference or NULL
+ */
+struct dirent *gn_directory_find(struct dirent *de, const gchar *filename)
+{
+ struct dirent *ret = NULL;
+
+ if(de->de_type != DE_DIR)
+ return NULL;
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
+ return NULL;
+ if(!de->de_cached)
{
- GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
- "%s: failed to download directory\n", __FUNCTION__);
- ret = -1;
- goto out;
+ if(directory_cache_locked(de) == -1)
+ goto out;
}
- ECRS_listDirectory(ectx, mem, len, &md, dir_for_each_cb, &d);
- ECRS_freeMetaData(md);
- ret = 0;
+ ret = g_hash_table_lookup(de->de_dir_hash, filename);
+ if(ret != NULL)
+ gn_dirent_ref(ret);
out:
- FREE(mem);
+ SEMAPHORE_UP(de->de_sema);
return ret;
}
-static int directory_insert_callback(struct dirent *de, const gchar *filename,
- void *data)
+int gn_directory_insert(struct dirent *de, struct dirent *dechild)
{
- struct dir_for_each_data *d = data;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+ __FUNCTION__, dechild->de_path);
- (void)filename;
- gn_dirent_ref(de);
- g_hash_table_replace(d->de->de_dir, de->de_path, de);
- return OK;
+ /* Lock our path */
+ if(gn_lock_path(de) == -1)
+ return -1;
+
+ /* Cache ourselfs (because we're going to become dirty) */
+ if(!de->de_cached)
+ {
+ if(directory_cache_locked(de) == -1)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: failed to cache parent dir\n",
+ __FUNCTION__);
+ gn_unlock_path(de, GN_UNLOCK_CLEAN);
+ return -1;
+ }
+ }
+
+ /* If we're already in there, bail out */
+ if(g_hash_table_lookup(de->de_dir_hash, dechild->de_basename))
+ {
+ gn_unlock_path(de, GN_UNLOCK_CLEAN);
+ return -1;
+ }
+
+ /* Insert the child in our de_dir_hash */
+ gn_dirent_ref(dechild);
+ g_hash_table_replace(de->de_dir_hash, dechild->de_basename, dechild);
+
+ /* Cache the dirent */
+ gn_dirent_cache(dechild);
+
+ /* Mark our path dirty */
+ gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
+ return 0;
}
-int gn_directory_insert(struct dirent *de_dir, struct dirent *de_new)
+static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
+ void *closure)
{
- struct dir_for_each_data d;
- void *mem;
- guint64 len;
+ (void)totalBytes;
+ (void)completedBytes;
+ (void)eta;
+ (void)closure;
+}
+
+struct dir_upload_data
+{
+ ECRS_FileInfo *fis;
+ int count;
+ int failed;
+};
+
+static gboolean dir_upload_callback(gpointer key, gpointer value, gpointer
data)
+{
+ struct dirent *de = value;
+ struct dir_upload_data *d = data;
int ret = 0;
- struct ECRS_MetaData *md;
- if(SEMAPHORE_DOWN(de_dir->de_file_sema, YES) == SYSERR)
- return -1;
- if(!de_dir->de_dirty)
+ (void)key;
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
{
- 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)
+ d->failed = 1;
+ return 1;
+ }
+ if(de->de_dirty)
+ {
+ if(de->de_type == DE_FILE)
{
- GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
- "%s: failed to download directory\n",
- __FUNCTION__);
- ret = -1;
- goto out;
+ if(de->de_fi.uri == NULL)
+ {
+ goto out;
+ }
}
- ECRS_listDirectory(ectx, mem, len, &md, dir_for_each_cb, &d);
- ECRS_freeMetaData(md);
+ else
+ {
+ if(gn_directory_upload_locked(de) == -1)
+ {
+ d->failed = 1;
+ ret = 1;
+ goto out;
+ }
+ }
}
- gn_dirent_ref(de_new);
- g_hash_table_replace(de_dir->de_dir, de_new->de_path, de_new);
+ d->fis[d->count].uri = ECRS_dupUri(de->de_fi.uri);
+ d->fis[d->count].meta = ECRS_dupMetaData(de->de_fi.meta);
+ d->count++;
out:
- SEMAPHORE_UP(de_dir->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
return ret;
}
+
+/*
+ * Make a directory clean, de_sema must be locked
+ */
+int gn_directory_upload_locked(struct dirent *de)
+{
+ int i, ret, fd;
+ char *buf, filename[] = GN_MKSTEMP_FILE;
+ guint64 len;
+ struct ECRS_URI *uri;
+ struct dir_upload_data d;
+
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: called for '%s'\n", __FUNCTION__, de->de_path);
+
+ /* We may be already clean */
+ if(!de->de_dirty)
+ return 0;
+
+ /* Collect FileInfo from hash table and make a GNUnet directory */
+ d.fis = MALLOC(g_hash_table_size(de->de_dir_hash) * sizeof(*d.fis));
+ d.count = 0;
+ d.failed = 0;
+ g_hash_table_find(de->de_dir_hash, dir_upload_callback, &d);
+ if(d.failed)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: failed\n", __FUNCTION__);
+ return -1;
+ }
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: creating dir of %d elements\n", __FUNCTION__, d.count);
+ ret = ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
+ de->de_fi.meta);
+ for(i = 0; i < d.count; i++)
+ {
+ ECRS_freeUri(d.fis[i].uri);
+ ECRS_freeMetaData(d.fis[i].meta);
+ }
+ FREE(d.fis);
+ if(ret == SYSERR)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: ECRS_createDirectory failed\n",
+ __FUNCTION__);
+ return -1;
+ }
+
+ /* Write the GNUnet directory out to a file and upload it */
+ fd = mkstemp(filename);
+ if(fd == -1)
+ {
+ GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
+ | GE_ERROR, "mkstemp", filename);
+ return -1;
+ }
+ write(fd, buf, len);
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: wrote to %lld bytes to '%s'\n", __FUNCTION__, len,
+ filename);
+ ret = ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
+ -1, upcb, NULL, tt, NULL, &uri);
+ close(fd);
+ unlink(filename);
+ if(ret == SYSERR)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: ECRS_uploadFile failed\n", __FUNCTION__);
+ return -1;
+ }
+
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: done\n", __FUNCTION__);
+ /* Update the dirent info with our new URI and mark it clean */
+ if(de->de_fi.uri != NULL)
+ ECRS_freeUri(de->de_fi.uri);
+ de->de_fi.uri = uri;
+ de->de_dirty = 0;
+ return 0;
+}
Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/dirent.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -32,9 +32,9 @@
*/
void gn_dirent_ref(struct dirent *de)
{
- MUTEX_LOCK(de->de_mutex);
+ MUTEX_LOCK(de->de_refs_mutex);
de->de_refs++;
- MUTEX_UNLOCK(de->de_mutex);
+ MUTEX_UNLOCK(de->de_refs_mutex);
}
/*
@@ -58,35 +58,38 @@
*/
void gn_dirent_put(struct dirent *de)
{
- MUTEX_LOCK(de->de_mutex);
+ MUTEX_LOCK(de->de_refs_mutex);
de->de_refs--;
- if(de->de_refs < 1)
+ if(de->de_refs >= 1)
{
- MUTEX_UNLOCK(de->de_mutex);
- MUTEX_DESTROY(de->de_mutex);
- FREE(de->de_path);
- 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)
+ MUTEX_UNLOCK(de->de_refs_mutex);
+ return;
+ }
+ MUTEX_UNLOCK(de->de_refs_mutex);
+ MUTEX_DESTROY(de->de_refs_mutex);
+ FREE(de->de_path);
+ SEMAPHORE_DESTROY(de->de_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_type == DE_DIR)
+ {
+ if(de->de_cached)
{
- 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);
- }
+ g_hash_table_destroy(de->de_dir_hash);
}
- FREE(de);
- return;
}
- MUTEX_UNLOCK(de->de_mutex);
+ else
+ {
+ if(de->de_cached)
+ {
+ close(de->de_fd);
+ unlink(de->de_filename);
+ FREE(de->de_filename);
+ }
+ }
+ FREE(de);
}
void gn_dirent_cache_init(void)
@@ -106,18 +109,21 @@
de = MALLOC(sizeof(*de));
de->de_path = STRDUP(path);
- de->de_mutex = MUTEX_CREATE(0);
+ de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+ de->de_refs_mutex = MUTEX_CREATE(0);
de->de_refs = 1;
de->de_type = type;
- de->de_file_sema = SEMAPHORE_CREATE(1);
+ de->de_sema = SEMAPHORE_CREATE(1);
if(uri != NULL)
{
- de->de_fi.uri = ECRS_dupUri(uri);
de->de_dirty = 0;
+ de->de_cached = 0;
+ de->de_fi.uri = ECRS_dupUri(uri);
}
else
{
de->de_dirty = 1;
+ de->de_cached = 1;
if(type == DE_FILE)
{
char filename[] = GN_MKSTEMP_FILE;
@@ -127,12 +133,14 @@
}
else
{
- de->de_dir = g_hash_table_new_full(g_str_hash,
- g_str_equal, NULL,
+ g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
(GDestroyNotify)gn_dirent_put);
}
}
- de->de_fi.meta = ECRS_dupMetaData(meta);
+ if(meta == NULL)
+ de->de_fi.meta = ECRS_createMetaData();
+ else
+ de->de_fi.meta = ECRS_dupMetaData(meta);
return de;
}
@@ -141,77 +149,62 @@
*/
void gn_dirent_cache(struct dirent *de)
{
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "%s: path '%s'\n", __FUNCTION__, de->de_path);
/* TODO: Here we need to see if the cache has gotten too big and empty
- * it */
- gn_dirent_ref(de);
+ * it.
+ * XXX: But what about diry entries?? */
if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
return;
+ GE_ASSERT(ectx, !g_hash_table_lookup(path_hash, de->de_path));
g_hash_table_replace(path_hash, de->de_path, de);
+ gn_dirent_ref(de);
SEMAPHORE_UP(path_sema);
}
-struct dirent_find_data
-{
- const gchar *name;
- struct dirent **de;
- gboolean found;
-};
-
-static gboolean dirent_find(struct dirent *de, const gchar *filename,
- void *data)
-{
- struct dirent_find_data *dfd = data;
-
- if(dfd->found == 1 || strcmp(filename, dfd->name) != 0)
- return OK;
-
- dfd->found = 1;
- gn_dirent_ref(de);
- *dfd->de = de;
- return SYSERR; /* It would be nice if this actually worked */
-}
-
/*
- * Retrieve a dirent with a reference given it's (normalized) path.
+ * Call 'cb' for each element in 'path', treats the empty string as "/"
*/
-struct dirent *gn_dirent_find(const gchar *path)
+int gn_path_foreach(const gchar *path, gn_dir_foreach_callback cb, void *data)
{
struct dirent *de, *next_de;
size_t len, plen;
- gchar *ppath;
- struct dirent_find_data dfd;
+ gchar *ppath, *filename;
/* Start de off at the root */
de = root_de;
gn_dirent_ref(de);
- /* Root shortcut */
- if(strcmp(path, G_DIR_SEPARATOR_S) == 0)
- return de;
-
- /* Allocate partial path buffer and start it at the root */
+ /* Allocate partial path buffer */
len = strlen(path);
ppath = MALLOC(len + 1);
plen = 0;
- /* Save pointer to next de for the callback function */
- dfd.de = &next_de;
-
- /* While we haven't reached the end of path, we have work to do */
- while(plen < len)
+ /* Loop through each path element */
+ for( ; ; )
{
+ /* Do callback for current element */
+ if(cb(de, data))
+ break;
+
+ /* Do we have any more work to do? */
+ if(plen >= len || path[plen + 1] == '\0'
+ || path[plen + 1] == G_DIR_SEPARATOR)
+ {
+ break;
+ }
+
/* Save pointer to ppath end */
- dfd.name = &ppath[plen + 1];
+ filename = &ppath[plen + 1];
/* Cat next path component */
- ppath[plen++] = G_DIR_SEPARATOR;
- for(;path[plen] != '\0' && path[plen] != G_DIR_SEPARATOR;plen++)
+ ppath[plen] = G_DIR_SEPARATOR;
+ for(plen++; path[plen] != '\0' && path[plen] != G_DIR_SEPARATOR;
+ plen++)
+ {
ppath[plen] = path[plen];
+ }
ppath[plen] = '\0';
- /* Look it up in the cache first */
+ /* Look it up in the cache first */
next_de = gn_dirent_get(ppath);
/* If we found it then continue */
@@ -226,154 +219,125 @@
}
/* We need to find it by listing its parent directory, de */
- if(de->de_type != DE_DIR)
- {
- gn_dirent_put(de);
- de = NULL;
- break;
- }
- dfd.found = 0;
- gn_directory_for_each(de, dirent_find, &dfd);
+ next_de = gn_directory_find(de, filename);
- /* Not found? Then why did they ask us? */
- if(!dfd.found)
+ /* Not found? */
+ if(next_de == NULL)
{
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "%s: not found!\n", __FUNCTION__);
gn_dirent_put(de);
de = NULL;
break;
}
-
- /* Continue to the next path element */
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
"%s: found in directory '%s'\n", __FUNCTION__,
next_de->de_path);
+
+ /* Continue to the next path element */
gn_dirent_put(de);
de = next_de;
}
/* Done */
FREE(ppath);
-
- return de;
+ if(de == NULL)
+ return -1;
+ gn_dirent_put(de);
+ return 0;
}
-struct upload_data
+static gboolean dirent_find_callback(struct dirent *de, void *data)
{
- int count;
- ECRS_FileInfo *fis;
-};
+ struct dirent **d = data;
-static void upload_foreach(gpointer key, gpointer value, gpointer data)
+ if(*d != NULL)
+ gn_dirent_put(*d);
+ *d = de;
+ gn_dirent_ref(*d);
+ return 0;
+}
+
+/*
+ * Retrieve a dirent with a reference given it's (normalized) path.
+ */
+struct dirent *gn_dirent_find(const gchar *path)
{
- struct dirent *de = value;
- struct upload_data *d = data;
+ struct dirent *de = NULL;
- (void)key;
-
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
- return;
- if(de->de_dirty)
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: called for '%s'\n", __FUNCTION__, path);
+ if(gn_path_foreach(path, dirent_find_callback, &de) == -1)
{
- if(de->de_type == DE_FILE)
- {
- if(de->de_fi.uri == NULL)
- goto out;
- }
- else
- {
- gn_dirent_upload_locked(de);
- }
+ if(de != NULL)
+ gn_dirent_put(de);
+ return NULL;
}
- d->fis[d->count].uri = ECRS_dupUri(de->de_fi.uri);
- d->fis[d->count].meta = ECRS_dupMetaData(de->de_fi.meta);
- d->count++;
-out:
- SEMAPHORE_UP(de->de_file_sema);
+ return de;
}
-static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
- void *closure)
+static gboolean lock_path_callback(struct dirent *de, void *data)
{
- (void)totalBytes;
- (void)completedBytes;
- (void)eta;
- (void)closure;
-}
+ struct dirent **detmp = data;
-static int tt(void *closure)
-{
- (void)closure;
-
- return fuse_interrupted() ? SYSERR : OK;
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == -1)
+ return 1;
+ gn_dirent_ref(de);
+ *detmp = de;
+ 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
+ * Locks each element in a path.
*/
-int gn_dirent_upload_locked(struct dirent *de)
+int gn_lock_path(struct dirent *de)
{
- int i, ret, fd;
- struct upload_data d;
- char *buf, filename[] = GN_MKSTEMP_FILE;
- guint64 len;
- struct ECRS_URI *uri;
+ struct dirent *detmp = NULL;
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "%s: called for '%s'\n", __FUNCTION__, de->de_path);
-
- /* We may be already clean */
- if(!de->de_dirty)
- return 0;
-
- /* Collect FileInfo from hash table and make a GNUnet directory*/
- d.count = 0;
- d.fis = MALLOC(g_hash_table_size(de->de_dir) * sizeof(*d.fis));
- g_hash_table_foreach(de->de_dir, upload_foreach, &d);
- ret = ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
- de->de_fi.meta);
- for(i = 0; i < d.count; i++)
+ if(gn_path_foreach(de->de_path, lock_path_callback, &detmp) == -1)
{
- ECRS_freeUri(d.fis[i].uri);
- ECRS_freeMetaData(d.fis[i].meta);
- }
- if(ret == SYSERR)
- {
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
- "%s: ECRS_createDirectory failed\n",
- __FUNCTION__);
+ "%s: failed!\n", __FUNCTION__);
+ /* Back out all the locks we aquired */
+ if(detmp != NULL)
+ gn_unlock_path(detmp, GN_UNLOCK_CLEAN);
return -1;
}
- FREE(d.fis);
+ return 0;
+}
- /* Write the GNUnet directory out to a file and upload it */
- fd = mkstemp(filename);
- if(fd == -1)
+struct unlock_path_data
+{
+ int dirty;
+ struct dirent *de;
+};
+
+static gboolean unlock_path_callback(struct dirent *de, void *data)
+{
+ struct unlock_path_data *d = data;
+
+ if(d->dirty == GN_UNLOCK_ALL_DIRTY)
+ de->de_dirty = 1;
+ else if(d->dirty == GN_UNLOCK_ANCESTORS_DIRTY && de != d->de)
+ de->de_dirty = 1;
+ SEMAPHORE_UP(de->de_sema);
+ gn_dirent_put(de);
+ return 0;
+}
+
+/*
+ * Un-lock each element in a path and set the dirty state
+ */
+int gn_unlock_path(struct dirent *de, int dirty)
+{
+ struct unlock_path_data d;
+
+ d.dirty = dirty;
+ d.de = de;
+ if(gn_path_foreach(de->de_path, unlock_path_callback, &d) == -1)
{
- GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
- | GE_ERROR, "mkstemp", filename);
- return -1;
- }
- write(fd, buf, len);
- ret = ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
- -1, upcb, NULL, tt, NULL, &uri);
- close(fd);
- unlink(filename);
- if(ret == SYSERR)
- {
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
- "%s: ECRS_uploadFile failed\n", __FUNCTION__);
+ "%s: failed!\n", __FUNCTION__);
return -1;
}
-
- /* Update the dirent info with our new URI and mark it clean */
- 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;
return 0;
}
@@ -391,15 +355,23 @@
(void)cls;
}
+static int tt(void *closure)
+{
+ (void)closure;
+ return fuse_interrupted() ? SYSERR : OK;
+}
+
/*
- * Download a file for writing, de_file_sema must be held.
+ * Download a file for writing, de_sema must be held.
*/
int gn_dirent_download_locked(struct dirent *de)
{
char filename[] = GN_MKSTEMP_FILE;
- /* We may already be dirty */
- if(!de->de_dirty)
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: called for '%s'\n",
+ __FUNCTION__, de->de_path);
+ /* We may already be cached */
+ if(de->de_cached)
return 0;
/* Do the download */
@@ -412,16 +384,20 @@
}
de->de_filename = STRDUP(filename);
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: downloading '%s'\n", __FUNCTION__, de->de_filename);
if(ECRS_downloadFile(ectx, cfg, de->de_fi.uri, filename, anonymity,
dpcb, NULL, tt, NULL) == SYSERR)
{
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: download failed\n", __FUNCTION__);
close(de->de_fd);
+ unlink(de->de_filename);
FREE(de->de_filename);
return -1;
}
- /* Mark ourselves dirty, we don't have to mark our parent directory
- * dirty until we sync this file back into GNUnet, see above. */
- de->de_dirty = 1;
+ /* Mark ourselves cached */
+ de->de_cached = 1;
return 0;
}
Modified: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/getattr.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -38,7 +38,8 @@
memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_mode = 0555 | S_IFREG;
stbuf->st_nlink = 1;
- stbuf->st_size = 0;
+ /* sysfs uses 4096 for variable sized files */
+ stbuf->st_size = 4096;
return 0;
}
@@ -55,9 +56,9 @@
stbuf->st_mode = 0777;
stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
stbuf->st_nlink = 1;
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
return -EIO;
- if(de->de_dirty)
+ if(de->de_cached)
{
if(de->de_type == DE_FILE && disk_file_size(ectx,
de->de_filename, &size, NO) == SYSERR)
@@ -65,7 +66,7 @@
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);
+ SEMAPHORE_UP(de->de_sema);
gn_dirent_put(de);
return -EIO;
}
@@ -74,7 +75,7 @@
{
size = ECRS_fileSize(de->de_fi.uri);
}
- SEMAPHORE_UP(de->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
gn_dirent_put(de);
stbuf->st_size = size;
return 0;
Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/gnfs.h 2007-07-12 06:15:47 UTC (rev 5302)
@@ -35,26 +35,33 @@
#define URI_FILE ".uri"
#define URI_LEN 4
#define GN_MKSTEMP_FILE "/tmp/gnfs.XXXXXX"
+#define GN_EMPTY_FILE_URI "gnunet://ecrs/chk/00000000000000000000000000000000"
\
+ "00000000000000000000000000000000000000000000000000000000000000000000" \
+ "000.0000000000000000000000000000000000000000000000000000000000000000" \
+ "000000000000000000000000000000000000000.0"
struct dirent
{
gchar *de_path;
- struct MUTEX *de_mutex;
+ gchar *de_basename;
+ struct MUTEX *de_refs_mutex;
gint de_refs;
gchar de_type;
#define DE_FILE 'f'
#define DE_DIR 'd'
- /* Access of anything below this must lock de_file_sema */
- struct SEMAPHORE *de_file_sema;
+ /* Access of anything below this must lock de_sema */
+ struct SEMAPHORE *de_sema;
+ /* Cached entries have their entire contents in memory or on disk */
+ gboolean de_cached;
+ /* Dirty entires have been changed and not published in GNUnet (implies
+ * cached) */
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 */
+ /* For cached directories */
+ GHashTable *de_dir_hash;
+ /* For cached files */
struct
{
gint de_fd;
@@ -63,11 +70,11 @@
};
};
-typedef int (*gn_dir_for_each_callback)(struct dirent *de,
- const gchar *filename, void *data);
+typedef gboolean (*gn_dir_foreach_callback)(struct dirent *de, void *data);
extern struct GC_Configuration *cfg;
extern struct GE_Context *ectx;
+extern int closing;
extern unsigned int anonymity;
extern unsigned int priority;
extern int uri_files;
@@ -82,13 +89,19 @@
void gn_dirent_cache_init(void);
void gn_dirent_cache(struct dirent *de);
struct dirent *gn_dirent_find(const gchar *path);
-int gn_dirent_upload_locked(struct dirent *de);
+int gn_lock_path(struct dirent *de);
+int gn_unlock_path(struct dirent *de, int dirty);
+#define GN_UNLOCK_CLEAN 0
+#define GN_UNLOCK_ALL_DIRTY 1
+#define GN_UNLOCK_ANCESTORS_DIRTY 2
int gn_dirent_download_locked(struct dirent *de);
/* directory.c */
-int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
+int gn_directory_foreach(struct dirent *de, gn_dir_foreach_callback cb,
void *data);
-int gn_directory_insert(struct dirent *de_dir, struct dirent *de_new);
+struct dirent *gn_directory_find(struct dirent *de, const gchar *filename);
+int gn_directory_insert(struct dirent *de, struct dirent *dechild);
+int gn_directory_upload_locked(struct dirent *de);
/* FUSE function files */
int gn_getattr(const char *path, struct stat *stbuf);
@@ -100,6 +113,7 @@
struct fuse_file_info *fi);
int gn_write(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi);
+int gn_release(const char *path, struct fuse_file_info *fi);
/* special_file.c */
char *gn_dirname(const char *path, char **file);
Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/main.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -36,6 +36,9 @@
static char *cfgFilename = DEFAULT_CLIENT_CONFIG_FILE;
static char *cfgLogfile = "/tmp/gnunet_fuse.log";
+/* Flag to indicate that we are shutting down */
+int closing = 0;
+
/* Level of anonymity for downloading and uploading files */
unsigned int anonymity = 1;
@@ -74,6 +77,7 @@
.open = gn_open,
.read = gn_read,
.write = gn_write,
+ .release = gn_release,
};
static struct CommandLineOption gn_options[] =
@@ -205,11 +209,15 @@
GE_LOG(ectx, GE_BULK | GE_USER | GE_DEBUG, "fuse_main returned\n");
/* Save root uri */
+ closing = 1;
buf = gn_get_special_file(G_DIR_SEPARATOR_S URI_FILE);
- ftruncate(root_fd, 0);
- lseek(root_fd, SEEK_SET, 0);
- write(root_fd, buf, strlen(buf));
- FREE(buf);
+ if(buf != NULL)
+ {
+ ftruncate(root_fd, 0);
+ lseek(root_fd, SEEK_SET, 0);
+ write(root_fd, buf, strlen(buf));
+ FREE(buf);
+ }
out_close_root:
disk_file_close(ectx, argv[i], root_fd);
quit:
Modified: gnunet-fuse/mknod.c
===================================================================
--- gnunet-fuse/mknod.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/mknod.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -28,8 +28,10 @@
int gn_mknod(const char *path, mode_t mode, dev_t rdev)
{
struct dirent *de, *newde;
+ struct ECRS_URI *uri;
struct ECRS_MetaData *meta;
char *parent, *file;
+ int ret;
(void)rdev;
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
@@ -59,19 +61,17 @@
FREE(parent);
return -ENOENT;
}
+ uri = ECRS_stringToUri(ectx, GN_EMPTY_FILE_URI);
meta = ECRS_createMetaData();
ECRS_addToMetaData(meta, EXTRACTOR_FILENAME, file);
- newde = gn_dirent_new(path, NULL, meta, DE_FILE);
+ newde = gn_dirent_new(path, uri, meta, DE_FILE);
ECRS_freeMetaData(meta);
- if(gn_directory_insert(de, newde) == -1)
- {
- gn_dirent_put(de);
- gn_dirent_put(newde);
- FREE(parent);
- return -EIO;
- }
+ ECRS_freeUri(uri);
+ ret = gn_directory_insert(de, newde);
gn_dirent_put(de);
gn_dirent_put(newde);
FREE(parent);
+ if(ret == -1)
+ return -EIO;
return 0;
}
Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/read.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -119,12 +119,12 @@
size = -ENOENT;
goto out;
}
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
{
size = -EIO;
goto out;
}
- if(de->de_dirty)
+ if(de->de_cached)
{
slen = pread(de->de_fd, buf, size, offset);
if(slen == -1)
@@ -155,7 +155,7 @@
size = -ENODATA;
}
out_sema_up:
- SEMAPHORE_UP(de->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
out:
gn_dirent_put(de);
return size;
Modified: gnunet-fuse/readdir.c
===================================================================
--- gnunet-fuse/readdir.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/readdir.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -37,8 +37,7 @@
const char *prefix;
};
-static int readdir_callback(struct dirent *de, const gchar *filename,
- void *data)
+static int readdir_callback(struct dirent *de, void *data)
{
struct readdir_callback_data *d = data;
@@ -46,15 +45,16 @@
if(d->prefix != NULL)
{
- char *buf = MALLOC(strlen(d->prefix) + strlen(filename) + 1);
+ char *buf = MALLOC(strlen(d->prefix) + strlen(de->de_basename)
+ + 1);
- sprintf(buf, "%s%s", d->prefix, filename);
+ sprintf(buf, "%s%s", d->prefix, de->de_basename);
d->filler(d->buf, buf, NULL, 0);
FREE(buf);
}
else
{
- d->filler(d->buf, filename, NULL, 0);
+ d->filler(d->buf, de->de_basename, NULL, 0);
}
return OK;
}
@@ -94,7 +94,7 @@
d.filler = filler;
d.buf = buf;
d.prefix = ".uri.";
- ret = gn_directory_for_each(de, readdir_callback, &d);
+ ret = gn_directory_foreach(de, readdir_callback, &d);
if(ret == -1)
{
ret = -ENOENT;
@@ -104,7 +104,7 @@
d.filler = filler;
d.buf = buf;
d.prefix = NULL;
- ret = gn_directory_for_each(de, readdir_callback, &d);
+ ret = gn_directory_foreach(de, readdir_callback, &d);
if(ret == -1)
ret = -ENOENT;
out:
Added: gnunet-fuse/release.c
===================================================================
--- gnunet-fuse/release.c (rev 0)
+++ gnunet-fuse/release.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -0,0 +1,101 @@
+/*
+ * release.c - FUSE release function
+ *
+ * This file is part of gnunet-fuse.
+ * Copyright (C) 2007 David Barksdale
+ *
+ * gnunet-fuse is free software; you can redistribute it and/or
+ * modify if under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * gnunet-fuse is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
+ void *closure)
+{
+ (void)totalBytes;
+ (void)completedBytes;
+ (void)eta;
+ (void)closure;
+}
+
+static int tt(void *closure)
+{
+ (void)closure;
+
+ return fuse_interrupted() ? SYSERR : OK;
+}
+
+int gn_release(const char *path, struct fuse_file_info *fi)
+{
+ struct dirent *de;
+ struct ECRS_URI *uri;
+ gboolean dirty = GN_UNLOCK_CLEAN;
+
+ (void)fi;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+ __FUNCTION__, path);
+
+ /* Don't do anything for special files */
+ if(gn_exists_special_file(path))
+ return 0;
+
+ /* If it doesn't exist we don't care */
+ de = gn_dirent_find(path);
+ if(de == NULL)
+ return 0;
+ if(de->de_type != DE_FILE)
+ {
+ /* XXX does this get called on directories?? */
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: not a file\n", __FUNCTION__);
+ gn_dirent_put(de);
+ return 0;
+ }
+
+ /* Lock our path */
+ if(gn_lock_path(de) == -1)
+ return 0;
+
+ /* If we're not dirty then we're done */
+ if(!de->de_dirty)
+ goto out;
+
+ /* Take this opportunity */
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: uploading file\n", __FUNCTION__);
+ if(ECRS_uploadFile(ectx, cfg, de->de_filename, NO, anonymity, priority,
+ -1, upcb, NULL, tt, NULL, &uri) == SYSERR)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: upload failed\n", __FUNCTION__);
+ goto out;
+ }
+ if(de->de_fi.uri != NULL)
+ ECRS_freeUri(de->de_fi.uri);
+ de->de_fi.uri = uri;
+ de->de_cached = 0;
+ de->de_dirty = 0;
+ close(de->de_fd);
+ unlink(de->de_filename);
+ FREE(de->de_filename);
+
+ /* Now we must mark every containing directory dirty */
+ dirty = GN_UNLOCK_ANCESTORS_DIRTY;
+out:
+ gn_unlock_path(de, dirty);
+ gn_dirent_put(de);
+ return 0;
+}
Modified: gnunet-fuse/special_file.c
===================================================================
--- gnunet-fuse/special_file.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/special_file.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -90,20 +90,22 @@
de = gn_dirent_find(parent);
if(de == NULL)
goto out;
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ if(SEMAPHORE_DOWN(de->de_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;
+ if(gn_directory_upload_locked(de) == -1)
+ {
+ SEMAPHORE_UP(de->de_sema);
+ gn_dirent_put(de);
+ goto out;
+ }
}
buf = ECRS_uriToString(de->de_fi.uri);
- SEMAPHORE_UP(de->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
gn_dirent_put(de);
buf = REALLOC(buf, strlen(buf) + 2);
strcat(buf, "\n");
@@ -119,20 +121,34 @@
FREE(actual_file);
if(de == NULL)
goto out;
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ if(SEMAPHORE_DOWN(de->de_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;
+ if(de->de_type == DE_DIR)
+ {
+ if(gn_directory_upload_locked(de) == -1)
+ {
+ SEMAPHORE_UP(de->de_sema);
+ gn_dirent_put(de);
+ goto out;
+ }
+ }
+ else
+ {
+ if(de->de_fi.uri == NULL)
+ {
+ SEMAPHORE_UP(de->de_sema);
+ gn_dirent_put(de);
+ goto out;
+ }
+ }
}
buf = ECRS_uriToString(de->de_fi.uri);
- SEMAPHORE_UP(de->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
gn_dirent_put(de);
buf = REALLOC(buf, strlen(buf) + 2);
strcat(buf, "\n");
Modified: gnunet-fuse/write.c
===================================================================
--- gnunet-fuse/write.c 2007-07-11 15:07:19 UTC (rev 5301)
+++ gnunet-fuse/write.c 2007-07-12 06:15:47 UTC (rev 5302)
@@ -56,13 +56,13 @@
goto out;
}
- /* We must be dirty */
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ /* We must be cached */
+ if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
{
size = -EIO;
goto out;
}
- if(!de->de_dirty)
+ if(!de->de_cached)
{
if(gn_dirent_download_locked(de) == -1)
{
@@ -77,8 +77,11 @@
size = -errno;
else
size = slen;
+
+ /* Mark us dirty */
+ de->de_dirty = 1;
out_unlock:
- SEMAPHORE_UP(de->de_file_sema);
+ SEMAPHORE_UP(de->de_sema);
out:
gn_dirent_put(de);
return size;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r5302 - gnunet-fuse,
gnunet <=