gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r20389 - in gnunet-fuse: . gnunet-fuse-v8


From: gnunet
Subject: [GNUnet-SVN] r20389 - in gnunet-fuse: . gnunet-fuse-v8
Date: Fri, 9 Mar 2012 09:38:55 +0100

Author: mauricio
Date: 2012-03-09 09:38:54 +0100 (Fri, 09 Mar 2012)
New Revision: 20389

Added:
   gnunet-fuse/gnunet-fuse-v8/
   gnunet-fuse/gnunet-fuse-v8/directory.c
   gnunet-fuse/gnunet-fuse-v8/dirent.c
   gnunet-fuse/gnunet-fuse-v8/file.c
   gnunet-fuse/gnunet-fuse-v8/getattr.c
   gnunet-fuse/gnunet-fuse-v8/main.c
   gnunet-fuse/gnunet-fuse-v8/mkdir.c
   gnunet-fuse/gnunet-fuse-v8/mknod.c
   gnunet-fuse/gnunet-fuse-v8/open.c
   gnunet-fuse/gnunet-fuse-v8/read.c
   gnunet-fuse/gnunet-fuse-v8/readdir.c
   gnunet-fuse/gnunet-fuse-v8/release.c
   gnunet-fuse/gnunet-fuse-v8/rename.c
   gnunet-fuse/gnunet-fuse-v8/rmdir.c
   gnunet-fuse/gnunet-fuse-v8/special_file.c
   gnunet-fuse/gnunet-fuse-v8/truncate.c
   gnunet-fuse/gnunet-fuse-v8/unlink.c
   gnunet-fuse/gnunet-fuse-v8/utimens.c
   gnunet-fuse/gnunet-fuse-v8/write.c
Removed:
   gnunet-fuse/directory.c
   gnunet-fuse/dirent.c
   gnunet-fuse/file.c
   gnunet-fuse/getattr.c
   gnunet-fuse/main.c
   gnunet-fuse/mkdir.c
   gnunet-fuse/mknod.c
   gnunet-fuse/open.c
   gnunet-fuse/read.c
   gnunet-fuse/readdir.c
   gnunet-fuse/release.c
   gnunet-fuse/rename.c
   gnunet-fuse/rmdir.c
   gnunet-fuse/special_file.c
   gnunet-fuse/truncate.c
   gnunet-fuse/unlink.c
   gnunet-fuse/utimens.c
   gnunet-fuse/write.c
Log:
moving old fuse code to backup directory


Deleted: gnunet-fuse/directory.c
===================================================================
--- gnunet-fuse/directory.c     2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/directory.c     2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,429 +0,0 @@
-/*
- * directory.c - stuff you want to do with directories
- *
- * 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 <sys/mman.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <glib.h>
-#include <GNUnet/gnunet_ecrs_lib.h>
-#include "gnfs.h"
-
-static void dpcb(unsigned long long totalBytes,
-       unsigned long long completedBytes, GNUNET_CronTime eta,
-       unsigned long long lastBlockOffset, const char *lastBlock,
-       unsigned int lastBlockSize, void *cls)
-{
-       (void)totalBytes;
-       (void)completedBytes;
-       (void)eta;
-       memcpy((char *)cls + lastBlockOffset, lastBlock, lastBlockSize);
-}
-
-static int tt(void *cls)
-{
-       (void)cls;
-       if(closing)
-               return GNUNET_OK;
-       if(fuse_interrupted())
-               return GNUNET_SYSERR;
-       return GNUNET_OK;
-}
-
-static int dir_cache_cb(const GNUNET_ECRS_FileInfo *fi, const GNUNET_HashCode 
*key,
-       int isRoot, void *data)
-{
-       struct dirent *de, *deparent = data;
-       gchar *filename, *path, *newpath, type;
-       size_t len, rlen;
-
-       (void)key;
-
-       if(isRoot == GNUNET_YES)
-               return GNUNET_OK;
-
-       /* Figure out the filename and type from metadata */
-       filename = GNUNET_meta_data_get_by_type(fi->meta, EXTRACTOR_FILENAME);
-       if(filename == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_WARNING,
-                       "%s: dirent has no filename\n", __FUNCTION__);
-               return GNUNET_OK;
-       }
-       len = strlen(filename);
-       if(GNUNET_meta_data_test_for_directory(fi->meta) == GNUNET_YES)
-       {
-               if(filename[len - 1] == '/' || filename[len - 1] == '\\')
-                       filename[len - 1] = '\0';
-               type = DE_DIR;
-       }
-       else
-               type = DE_FILE;
-
-       /* Create newpath, the path to this entry */
-       path = gn_dirent_path_get(deparent);
-       rlen = strlen(path);
-       newpath = GNUNET_malloc(rlen + len + 1);
-       strcpy(newpath, path);
-       if(path[rlen - 1] != G_DIR_SEPARATOR)
-               strcat(newpath, G_DIR_SEPARATOR_S);
-       GNUNET_free(path);
-       strcat(newpath, filename);
-
-       /* 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 (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_insert(de);
-       }
-
-       /* Add it to the directory's list (steals our ref)*/
-       GNUNET_mutex_lock(de->de_path_mutex);
-       GNUNET_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);
-       GNUNET_mutex_unlock(de->de_path_mutex);
-
-       /* Clean up */
-       GNUNET_free(filename);
-       GNUNET_free(newpath);
-       return GNUNET_OK;
-}
-
-static int directory_cache_locked(struct dirent *de)
-{
-       struct GNUNET_MetaData *md;
-       void *mem;
-       int ret;
-       guint64 len;
-
-       len = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
-       mem = GNUNET_malloc(len);
-       ret = GNUNET_ECRS_file_download_partial(ectx, cfg, de->de_fi.uri,
-               "/dev/null", 0, len, anonymity, GNUNET_YES, dpcb, mem, tt,
-               NULL);
-       if(ret != GNUNET_OK)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_ERROR,
-                       "%s: failed to download directory\n",
-                       __FUNCTION__);
-               GNUNET_free(mem);
-               return -1;
-       }
-       de->de_dir_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-               (GDestroyNotify)gn_dirent_put);
-       GNUNET_ECRS_directory_list_contents(ectx, mem, len, NULL, &md, 
dir_cache_cb, de);
-       GNUNET_free(mem);
-       GNUNET_meta_data_destroy(md);
-       de->de_cached = 1;
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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;
-       return d->cb(de, d->data) == -1;
-}
-
-/*
- * Call cb for each element in a directory
- */
-int gn_directory_foreach(struct dirent *de, gn_dir_foreach_callback cb,
-       void *data)
-{
-       struct dir_foreach_data d;
-       int ret = 0;
-
-       if(de->de_type != DE_DIR)
-               return -1;
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-               return -1;
-       if(!de->de_cached)
-       {
-               ret = directory_cache_locked(de);
-               if(ret == -1)
-                       goto out;
-       }
-       d.cb = cb;
-       d.data = data;
-       g_hash_table_find(de->de_dir_hash, dir_foreach_callback, &d);
-out:
-       GNUNET_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(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-               return NULL;
-       if(!de->de_cached)
-       {
-               if(directory_cache_locked(de) == -1)
-                       goto out;
-       }
-       ret = g_hash_table_lookup(de->de_dir_hash, filename);
-       if(ret != NULL)
-               gn_dirent_ref(ret);
-out:
-       GNUNET_semaphore_up(de->de_sema);
-       return ret;
-}
-
-int gn_directory_insert(struct dirent *de, struct dirent *dechild)
-{
-       /* 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)
-               {
-                       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER | GNUNET_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 */
-       GNUNET_mutex_lock(dechild->de_path_mutex);
-       if(g_hash_table_lookup(de->de_dir_hash, dechild->de_basename))
-       {
-               GNUNET_mutex_unlock(dechild->de_path_mutex);
-               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);
-       GNUNET_mutex_unlock(dechild->de_path_mutex);
-
-       /* Cache the dirent */
-       gn_dirent_cache_insert(dechild);
-
-       /* Mark our path dirty */
-       gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
-       return 0;
-}
-
-int gn_directory_remove(struct dirent *de, struct dirent *dechild)
-{
-       /* 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)
-               {
-                       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER | GNUNET_GE_ERROR,
-                               "%s: failed to cache parent dir\n",
-                               __FUNCTION__);
-                       goto out_err;
-               }
-       }
-
-       /* Remove from dir_hash */
-       GNUNET_mutex_lock(dechild->de_path_mutex);
-       if(!g_hash_table_remove(de->de_dir_hash, dechild->de_basename))
-       {
-               GNUNET_mutex_unlock(dechild->de_path_mutex);
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: not found in dir_hash\n",
-                       __FUNCTION__);
-               goto out_err;
-       }
-       GNUNET_mutex_unlock(dechild->de_path_mutex);
-
-       /* Remove from dirent cache */
-       gn_dirent_cache_remove(dechild);
-
-       /* Mark our path dirty */
-       gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
-       return 0;
-out_err:
-       gn_unlock_path(de, GN_UNLOCK_CLEAN);
-       return -1;
-}
-
-static void upcb(unsigned long long totalBytes, 
-                unsigned long long completedBytes, GNUNET_CronTime eta,
-       void *closure)
-{
-       (void)totalBytes;
-       (void)completedBytes;
-       (void)eta;
-       (void)closure;
-}
-
-struct dir_upload_data
-{
-       GNUNET_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;
-
-       (void)key;
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-       {
-               d->failed = 1;
-               return 1;
-       }
-       if(de->de_dirty)
-       {
-               if(de->de_type == DE_FILE)
-               {
-                       if(de->de_fi.uri == NULL)
-                       {
-                               goto out;
-                       }
-               }
-               else
-               {
-                       if(gn_directory_upload_locked(de) == -1)
-                       {
-                               d->failed = 1;
-                               ret = 1;
-                               goto out;
-                       }
-               }
-       }
-       d->fis[d->count].uri = GNUNET_ECRS_uri_duplicate(de->de_fi.uri);
-       d->fis[d->count].meta = GNUNET_meta_data_duplicate(de->de_fi.meta);
-       d->count++;
-out:
-       GNUNET_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;
-       unsigned long long len;
-       struct GNUNET_ECRS_URI *uri;
-       struct dir_upload_data d;
-
-       /* We may be already clean */
-       if(!de->de_dirty)
-               return 0;
-
-       /* Collect FileInfo from hash table and make a GNUnet directory */
-       d.fis = GNUNET_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)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: failed\n", __FUNCTION__);
-               return -1;
-       }
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: creating dir of %d elements\n", __FUNCTION__, d.count);
-       ret = GNUNET_ECRS_directory_create(ectx, &buf, &len, d.count, d.fis,
-               de->de_fi.meta);
-       for(i = 0; i < d.count; i++)
-       {
-               GNUNET_ECRS_uri_destroy(d.fis[i].uri);
-               GNUNET_meta_data_destroy(d.fis[i].meta);
-       }
-       GNUNET_free(d.fis);
-       if(ret == GNUNET_SYSERR)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: GNUNET_ECRS_directory_create failed\n",
-                       __FUNCTION__);
-               return -1;
-       }
-
-       /* Write the GNUnet directory out to a file and upload it */
-       fd = mkstemp(filename);
-       if(fd == -1)
-       {
-               GNUNET_GE_LOG_STRERROR_FILE(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER
-                       | GNUNET_GE_ERROR, "mkstemp", filename);
-               return -1;
-       }
-       write(fd, buf, len);
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: wrote to %lld bytes to '%s'\n", __FUNCTION__, len,
-               filename);
-       ret = GNUNET_ECRS_file_upload(ectx, cfg, filename, GNUNET_NO, 
anonymity, priority,
-               -1, upcb, NULL, tt, NULL, &uri);
-       close(fd);
-       unlink(filename);
-       if(ret == GNUNET_SYSERR)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: GNUNET_ECRS_file_upload failed\n", __FUNCTION__);
-               return -1;
-       }
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: done\n", __FUNCTION__);
-       /* Update the dirent info with our new URI and mark it clean */
-       if(de->de_fi.uri != NULL)
-               GNUNET_ECRS_uri_destroy(de->de_fi.uri);
-       de->de_fi.uri = uri;
-       de->de_dirty = 0;
-       return 0;
-}

Deleted: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c        2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/dirent.c        2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,385 +0,0 @@
-/*
- * dirent.c - stuff for directory entries
- *
- * 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 <glib.h>
-#include <string.h>
-#include <errno.h>
-#include "gnfs.h"
-
-GHashTable *path_hash;
-struct GNUNET_Semaphore *path_sema;
-
-/*
- * Reference a dirent, call gn_dirent_put when finished
- */
-void gn_dirent_ref(struct dirent *de)
-{
-       GNUNET_mutex_lock(de->de_refs_mutex);
-       de->de_refs++;
-       GNUNET_mutex_unlock(de->de_refs_mutex);
-}
-
-/*
- * Reference a dirent from the cache, call gn_dirent_put when finished with it
- */
-struct dirent *gn_dirent_get(const gchar *path)
-{
-       struct dirent *de;
-
-       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
-               return NULL;
-       de = g_hash_table_lookup(path_hash, path);
-       if(de != NULL)
-               gn_dirent_ref(de);
-       GNUNET_semaphore_up(path_sema);
-       return de;
-}
-
-/*
- * Release a reference to a dirent
- */
-void gn_dirent_put(struct dirent *de)
-{
-       GNUNET_mutex_lock(de->de_refs_mutex);
-       de->de_refs--;
-       if(de->de_refs >= 1)
-       {
-               GNUNET_mutex_unlock(de->de_refs_mutex);
-               return;
-       }
-       GNUNET_mutex_unlock(de->de_refs_mutex);
-       GNUNET_mutex_destroy(de->de_path_mutex);
-       GNUNET_free(de->de_path);
-       GNUNET_mutex_destroy(de->de_refs_mutex);
-       GNUNET_semaphore_destroy(de->de_sema);
-       if(de->de_fi.uri != NULL)
-               GNUNET_ECRS_uri_destroy(de->de_fi.uri);
-       if(de->de_fi.meta != NULL)
-               GNUNET_meta_data_destroy(de->de_fi.meta);
-       if(de->de_type == DE_DIR)
-       {
-               if(de->de_cached)
-               {
-                       g_hash_table_destroy(de->de_dir_hash);
-               }
-       }
-       else
-       {
-               if(de->de_cached)
-               {
-                       close(de->de_fd);
-                       unlink(de->de_filename);
-                       GNUNET_free(de->de_filename);
-               }
-       }
-       GNUNET_free(de);
-}
-
-char *gn_dirent_path_get(struct dirent *de)
-{
-       char *ret;
-
-       GNUNET_mutex_lock(de->de_path_mutex);
-       ret = GNUNET_strdup(de->de_path);
-       GNUNET_mutex_unlock(de->de_path_mutex);
-       return ret;
-}
-
-/*
- * DON'T call this if the dirent is ref'd by a hash
- */
-void gn_dirent_path_set(struct dirent *de, const char *path)
-{
-       GNUNET_mutex_lock(de->de_path_mutex);
-       GNUNET_free(de->de_path);
-       de->de_path = GNUNET_strdup(path);
-       de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
-       GNUNET_mutex_unlock(de->de_path_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 = GNUNET_semaphore_create(1);
-}
-
-/*
- * Create a new dirent with a reference, path and uri are copied
- */
-struct dirent *gn_dirent_new(const gchar *path, struct GNUNET_ECRS_URI *uri,
-       struct GNUNET_MetaData *meta, gchar type)
-{
-       struct dirent *de;
-
-       de = GNUNET_malloc(sizeof(*de));
-       de->de_path_mutex = GNUNET_mutex_create(0);
-       de->de_path = GNUNET_strdup(path);
-       de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
-       de->de_refs_mutex = GNUNET_mutex_create(0);
-       de->de_refs = 1;
-       de->de_type = type;
-       de->de_sema = GNUNET_semaphore_create(1);
-       if(uri != NULL)
-       {
-               de->de_dirty = 0;
-               de->de_cached = 0;
-               de->de_fi.uri = GNUNET_ECRS_uri_duplicate(uri);
-       }
-       else
-       {
-               de->de_dirty = 1;
-               de->de_cached = 1;
-               if(type == DE_FILE)
-               {
-                       char filename[] = GN_MKSTEMP_FILE;
-
-                       de->de_fd = mkstemp(filename);
-                       de->de_filename = GNUNET_strdup(filename);
-               }
-               else
-               {
-                       de->de_dir_hash = g_hash_table_new_full(g_str_hash,
-                               g_str_equal, NULL,
-                               (GDestroyNotify)gn_dirent_put);
-               }
-       }
-       if(meta == NULL)
-               de->de_fi.meta = GNUNET_meta_data_create();
-       else
-               de->de_fi.meta = GNUNET_meta_data_duplicate(meta);
-       return de;
-}
-
-/*
- * Add a dirent to the cache
- */
-void gn_dirent_cache_insert(struct dirent *de)
-{
-       /* TODO: Here we need to see if the cache has gotten too big and empty
-        * it.
-        * XXX: But what about diry entries?? */
-       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
-               return;
-       GNUNET_mutex_lock(de->de_path_mutex);
-       GNUNET_GE_ASSERT(ectx, !g_hash_table_lookup(path_hash, de->de_path));
-       g_hash_table_replace(path_hash, de->de_path, de);
-       GNUNET_mutex_unlock(de->de_path_mutex);
-       gn_dirent_ref(de);
-       GNUNET_semaphore_up(path_sema);
-}
-
-/*
- * Remove a dirent from the cache
- */
-void gn_dirent_cache_remove(struct dirent *de)
-{
-       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
-               return;
-       /* This is safe because we still hold a ref */
-       GNUNET_mutex_lock(de->de_path_mutex);
-       g_hash_table_remove(path_hash, de->de_path);
-       GNUNET_mutex_unlock(de->de_path_mutex);
-       GNUNET_semaphore_up(path_sema);
-}
-
-/*
- * Call 'cb' for each element in 'path', treats the empty string as "/"
- */
-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, *filename;
-
-       /* Start de off at the root */
-       de = root_de;
-       gn_dirent_ref(de);
-
-       /* Allocate partial path buffer */
-       len = strlen(path);
-       ppath = GNUNET_malloc(len + 1);
-       plen = 0;
-
-       /* 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 */
-               filename = &ppath[plen + 1];
-
-               /* Cat next path component */
-               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 */
-               next_de = gn_dirent_get(ppath);
-
-               /* If we found it then continue */
-               if(next_de != NULL)
-               {
-                       gn_dirent_put(de);
-                       de = next_de;
-                       continue;
-               }
-
-               /* We need to find it by listing its parent directory, de */
-               next_de = gn_directory_find(de, filename);
-
-               /* Not found? */
-               if(next_de == NULL)
-               {
-                       gn_dirent_put(de);
-                       de = NULL;
-                       break;
-               }
-
-               /* Continue to the next path element */
-               gn_dirent_put(de);
-               de = next_de;
-       }
-
-       /* Done */
-       GNUNET_free(ppath);
-       if(de == NULL)
-               return -1;
-       gn_dirent_put(de);
-       return 0;
-}
-
-static gboolean dirent_find_callback(struct dirent *de, void *data)
-{
-       struct dirent **d = 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 = NULL;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: called for '%s'\n", __FUNCTION__, path);
-       if(gn_path_foreach(path, dirent_find_callback, &de) == -1)
-       {
-               if(de != NULL)
-                       gn_dirent_put(de);
-               return NULL;
-       }
-       return de;
-}
-
-static gboolean lock_path_callback(struct dirent *de, void *data)
-{
-       struct dirent **detmp = data;
-
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == -1)
-               return 1;
-       gn_dirent_ref(de);
-       *detmp = de;
-       return 0;
-}
-
-/*
- * Locks each element in a path.
- */
-int gn_lock_path(struct dirent *de)
-{
-       struct dirent *detmp = NULL;
-       char *path;
-
-       path = gn_dirent_path_get(de);
-       if(gn_path_foreach(path, lock_path_callback, &detmp) == -1)
-       {
-               GNUNET_free(path);
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: failed!\n", __FUNCTION__);
-               /* Back out all the locks we aquired */
-               if(detmp != NULL)
-                       gn_unlock_path(detmp, GN_UNLOCK_CLEAN);
-               return -1;
-       }
-       GNUNET_free(path);
-       return 0;
-}
-
-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;
-       GNUNET_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;
-       char *path;
-
-       d.dirty = dirty;
-       d.de = de;
-       path = gn_dirent_path_get(de);
-       if(gn_path_foreach(path, unlock_path_callback, &d) == -1)
-       {
-               GNUNET_free(path);
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: failed!\n", __FUNCTION__);
-               return -1;
-       }
-       GNUNET_free(path);
-       return 0;
-}

Deleted: gnunet-fuse/file.c
===================================================================
--- gnunet-fuse/file.c  2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/file.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,126 +0,0 @@
-/*
- * file.c - operations on files
- *
- * 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 <sys/mman.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <glib.h>
-#include <GNUnet/gnunet_ecrs_lib.h>
-#include "gnfs.h"
-
-static int tt(void *cls)
-{
-       (void)cls;
-       if(closing)
-               return GNUNET_OK;
-       if(fuse_interrupted())
-               return GNUNET_SYSERR;
-       return GNUNET_OK;
-}
-
-static void upcb(unsigned long long totalBytes, 
-                unsigned long long completedBytes, GNUNET_CronTime eta,
-       void *closure)
-{
-       (void)totalBytes;
-       (void)completedBytes;
-       (void)eta;
-       (void)closure;
-}
-
-static void dpcb(unsigned long long totalBytes,
-        unsigned long long completedBytes, GNUNET_CronTime eta,
-        unsigned long long lastBlockOffset, const char *lastBlock,
-        unsigned int lastBlockSize, void *cls)
-{
-       (void)totalBytes;
-       (void)completedBytes;
-       (void)eta;
-       (void)lastBlockOffset;
-       (void)lastBlock;
-       (void)lastBlockSize;
-       (void)cls;
-}
-
-/*
- * Download a file for writing, de_sema must be held.
- */
-int gn_file_download_locked(struct dirent *de)
-{
-       char filename[] = GN_MKSTEMP_FILE;
-
-       /* We may already be cached */
-       if(de->de_cached)
-               return 0;
-
-       /* Do the download */
-       de->de_fd = mkstemp(filename);
-       if(de->de_fd == -1)
-       {
-               GNUNET_GE_LOG_STRERROR_FILE(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER
-                       | GNUNET_GE_ERROR, "mkstemp", filename);
-               return -1;
-       }
-       de->de_filename = GNUNET_strdup(filename);
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: downloading '%s'\n", __FUNCTION__, de->de_filename);
-       if(GNUNET_ECRS_file_download(ectx, cfg, de->de_fi.uri, filename, 
anonymity,
-               dpcb, NULL, tt, NULL) == GNUNET_SYSERR)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: download failed\n", __FUNCTION__);
-               close(de->de_fd);
-               unlink(de->de_filename);
-               GNUNET_free(de->de_filename);
-               return -1;
-       }
-
-       /* Mark ourselves cached */
-       de->de_cached = 1;
-       return 0;
-}
-
-int gn_file_upload_locked(struct dirent *de)
-{
-       struct GNUNET_ECRS_URI *uri;
-
-       /* If we're not dirty then we're done */
-       if(!de->de_dirty)
-               return 0;
-
-       if(GNUNET_ECRS_file_upload(ectx, cfg, de->de_filename, GNUNET_NO, 
anonymity, priority,
-               -1, upcb, NULL, tt, NULL, &uri) == GNUNET_SYSERR)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
-                       "%s: upload failed\n", __FUNCTION__);
-               return -1;
-       }
-       if(de->de_fi.uri != NULL)
-               GNUNET_ECRS_uri_destroy(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);
-       GNUNET_free(de->de_filename);
-       return 0;
-}

Deleted: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c       2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/getattr.c       2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,86 +0,0 @@
-/*
- * getattr.c - FUSE getattr 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 <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_getattr(const char *path, struct stat *stbuf)
-{
-       struct dirent *de;
-       int ret = 0;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* Check to see if this is a special file */
-       if(gn_exists_special_file(path))
-       {
-               memset(stbuf, 0, sizeof(*stbuf));
-               stbuf->st_mode = 0555 | S_IFREG;
-               stbuf->st_nlink = 1;
-               /* sysfs uses 4096 for variable sized files */
-               stbuf->st_size = 4096;
-               return 0;
-       }
-
-       /* Fill in dirent stat info */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_DEBUG,
-                       "%s: could not find path '%s'\n", __FUNCTION__, path);
-               return -ENOENT;
-       }
-
-       /* If it's a cached file just call stat */
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-       {
-               gn_dirent_put(de);
-               return -EIO;
-       }
-       if(de->de_cached && de->de_type == DE_FILE)
-       {
-               ret = stat(de->de_filename, stbuf);
-               if(ret == -1)
-               {
-                       ret = -errno;
-                       GNUNET_GE_LOG_STRERROR(ectx, GNUNET_GE_BULK | 
GNUNET_GE_USER | GNUNET_GE_ERROR,
-                               "stat");
-                       goto out;
-               }
-               goto out;
-       }
-
-       memset(stbuf, 0, sizeof(*stbuf));
-       stbuf->st_mode = 0777;
-       stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
-       stbuf->st_nlink = 1;
-       if(de->de_fi.uri != NULL)
-               stbuf->st_size = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
-       else
-               stbuf->st_size = 0;
-out:
-       GNUNET_semaphore_up(de->de_sema);
-       gn_dirent_put(de);
-       return ret;
-}

Copied: gnunet-fuse/gnunet-fuse-v8/directory.c (from rev 20388, 
gnunet-fuse/directory.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/directory.c                              (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/directory.c      2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,429 @@
+/*
+ * directory.c - stuff you want to do with directories
+ *
+ * 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 <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <GNUnet/gnunet_ecrs_lib.h>
+#include "gnfs.h"
+
+static void dpcb(unsigned long long totalBytes,
+       unsigned long long completedBytes, GNUNET_CronTime eta,
+       unsigned long long lastBlockOffset, const char *lastBlock,
+       unsigned int lastBlockSize, void *cls)
+{
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       memcpy((char *)cls + lastBlockOffset, lastBlock, lastBlockSize);
+}
+
+static int tt(void *cls)
+{
+       (void)cls;
+       if(closing)
+               return GNUNET_OK;
+       if(fuse_interrupted())
+               return GNUNET_SYSERR;
+       return GNUNET_OK;
+}
+
+static int dir_cache_cb(const GNUNET_ECRS_FileInfo *fi, const GNUNET_HashCode 
*key,
+       int isRoot, void *data)
+{
+       struct dirent *de, *deparent = data;
+       gchar *filename, *path, *newpath, type;
+       size_t len, rlen;
+
+       (void)key;
+
+       if(isRoot == GNUNET_YES)
+               return GNUNET_OK;
+
+       /* Figure out the filename and type from metadata */
+       filename = GNUNET_meta_data_get_by_type(fi->meta, EXTRACTOR_FILENAME);
+       if(filename == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_WARNING,
+                       "%s: dirent has no filename\n", __FUNCTION__);
+               return GNUNET_OK;
+       }
+       len = strlen(filename);
+       if(GNUNET_meta_data_test_for_directory(fi->meta) == GNUNET_YES)
+       {
+               if(filename[len - 1] == '/' || filename[len - 1] == '\\')
+                       filename[len - 1] = '\0';
+               type = DE_DIR;
+       }
+       else
+               type = DE_FILE;
+
+       /* Create newpath, the path to this entry */
+       path = gn_dirent_path_get(deparent);
+       rlen = strlen(path);
+       newpath = GNUNET_malloc(rlen + len + 1);
+       strcpy(newpath, path);
+       if(path[rlen - 1] != G_DIR_SEPARATOR)
+               strcat(newpath, G_DIR_SEPARATOR_S);
+       GNUNET_free(path);
+       strcat(newpath, filename);
+
+       /* 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 (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_insert(de);
+       }
+
+       /* Add it to the directory's list (steals our ref)*/
+       GNUNET_mutex_lock(de->de_path_mutex);
+       GNUNET_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);
+       GNUNET_mutex_unlock(de->de_path_mutex);
+
+       /* Clean up */
+       GNUNET_free(filename);
+       GNUNET_free(newpath);
+       return GNUNET_OK;
+}
+
+static int directory_cache_locked(struct dirent *de)
+{
+       struct GNUNET_MetaData *md;
+       void *mem;
+       int ret;
+       guint64 len;
+
+       len = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
+       mem = GNUNET_malloc(len);
+       ret = GNUNET_ECRS_file_download_partial(ectx, cfg, de->de_fi.uri,
+               "/dev/null", 0, len, anonymity, GNUNET_YES, dpcb, mem, tt,
+               NULL);
+       if(ret != GNUNET_OK)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_ERROR,
+                       "%s: failed to download directory\n",
+                       __FUNCTION__);
+               GNUNET_free(mem);
+               return -1;
+       }
+       de->de_dir_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+               (GDestroyNotify)gn_dirent_put);
+       GNUNET_ECRS_directory_list_contents(ectx, mem, len, NULL, &md, 
dir_cache_cb, de);
+       GNUNET_free(mem);
+       GNUNET_meta_data_destroy(md);
+       de->de_cached = 1;
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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;
+       return d->cb(de, d->data) == -1;
+}
+
+/*
+ * Call cb for each element in a directory
+ */
+int gn_directory_foreach(struct dirent *de, gn_dir_foreach_callback cb,
+       void *data)
+{
+       struct dir_foreach_data d;
+       int ret = 0;
+
+       if(de->de_type != DE_DIR)
+               return -1;
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+               return -1;
+       if(!de->de_cached)
+       {
+               ret = directory_cache_locked(de);
+               if(ret == -1)
+                       goto out;
+       }
+       d.cb = cb;
+       d.data = data;
+       g_hash_table_find(de->de_dir_hash, dir_foreach_callback, &d);
+out:
+       GNUNET_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(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+               return NULL;
+       if(!de->de_cached)
+       {
+               if(directory_cache_locked(de) == -1)
+                       goto out;
+       }
+       ret = g_hash_table_lookup(de->de_dir_hash, filename);
+       if(ret != NULL)
+               gn_dirent_ref(ret);
+out:
+       GNUNET_semaphore_up(de->de_sema);
+       return ret;
+}
+
+int gn_directory_insert(struct dirent *de, struct dirent *dechild)
+{
+       /* 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)
+               {
+                       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER | GNUNET_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 */
+       GNUNET_mutex_lock(dechild->de_path_mutex);
+       if(g_hash_table_lookup(de->de_dir_hash, dechild->de_basename))
+       {
+               GNUNET_mutex_unlock(dechild->de_path_mutex);
+               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);
+       GNUNET_mutex_unlock(dechild->de_path_mutex);
+
+       /* Cache the dirent */
+       gn_dirent_cache_insert(dechild);
+
+       /* Mark our path dirty */
+       gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
+       return 0;
+}
+
+int gn_directory_remove(struct dirent *de, struct dirent *dechild)
+{
+       /* 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)
+               {
+                       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER | GNUNET_GE_ERROR,
+                               "%s: failed to cache parent dir\n",
+                               __FUNCTION__);
+                       goto out_err;
+               }
+       }
+
+       /* Remove from dir_hash */
+       GNUNET_mutex_lock(dechild->de_path_mutex);
+       if(!g_hash_table_remove(de->de_dir_hash, dechild->de_basename))
+       {
+               GNUNET_mutex_unlock(dechild->de_path_mutex);
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: not found in dir_hash\n",
+                       __FUNCTION__);
+               goto out_err;
+       }
+       GNUNET_mutex_unlock(dechild->de_path_mutex);
+
+       /* Remove from dirent cache */
+       gn_dirent_cache_remove(dechild);
+
+       /* Mark our path dirty */
+       gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
+       return 0;
+out_err:
+       gn_unlock_path(de, GN_UNLOCK_CLEAN);
+       return -1;
+}
+
+static void upcb(unsigned long long totalBytes, 
+                unsigned long long completedBytes, GNUNET_CronTime eta,
+       void *closure)
+{
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       (void)closure;
+}
+
+struct dir_upload_data
+{
+       GNUNET_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;
+
+       (void)key;
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+       {
+               d->failed = 1;
+               return 1;
+       }
+       if(de->de_dirty)
+       {
+               if(de->de_type == DE_FILE)
+               {
+                       if(de->de_fi.uri == NULL)
+                       {
+                               goto out;
+                       }
+               }
+               else
+               {
+                       if(gn_directory_upload_locked(de) == -1)
+                       {
+                               d->failed = 1;
+                               ret = 1;
+                               goto out;
+                       }
+               }
+       }
+       d->fis[d->count].uri = GNUNET_ECRS_uri_duplicate(de->de_fi.uri);
+       d->fis[d->count].meta = GNUNET_meta_data_duplicate(de->de_fi.meta);
+       d->count++;
+out:
+       GNUNET_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;
+       unsigned long long len;
+       struct GNUNET_ECRS_URI *uri;
+       struct dir_upload_data d;
+
+       /* We may be already clean */
+       if(!de->de_dirty)
+               return 0;
+
+       /* Collect FileInfo from hash table and make a GNUnet directory */
+       d.fis = GNUNET_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)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: failed\n", __FUNCTION__);
+               return -1;
+       }
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: creating dir of %d elements\n", __FUNCTION__, d.count);
+       ret = GNUNET_ECRS_directory_create(ectx, &buf, &len, d.count, d.fis,
+               de->de_fi.meta);
+       for(i = 0; i < d.count; i++)
+       {
+               GNUNET_ECRS_uri_destroy(d.fis[i].uri);
+               GNUNET_meta_data_destroy(d.fis[i].meta);
+       }
+       GNUNET_free(d.fis);
+       if(ret == GNUNET_SYSERR)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: GNUNET_ECRS_directory_create failed\n",
+                       __FUNCTION__);
+               return -1;
+       }
+
+       /* Write the GNUnet directory out to a file and upload it */
+       fd = mkstemp(filename);
+       if(fd == -1)
+       {
+               GNUNET_GE_LOG_STRERROR_FILE(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER
+                       | GNUNET_GE_ERROR, "mkstemp", filename);
+               return -1;
+       }
+       write(fd, buf, len);
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: wrote to %lld bytes to '%s'\n", __FUNCTION__, len,
+               filename);
+       ret = GNUNET_ECRS_file_upload(ectx, cfg, filename, GNUNET_NO, 
anonymity, priority,
+               -1, upcb, NULL, tt, NULL, &uri);
+       close(fd);
+       unlink(filename);
+       if(ret == GNUNET_SYSERR)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: GNUNET_ECRS_file_upload failed\n", __FUNCTION__);
+               return -1;
+       }
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: done\n", __FUNCTION__);
+       /* Update the dirent info with our new URI and mark it clean */
+       if(de->de_fi.uri != NULL)
+               GNUNET_ECRS_uri_destroy(de->de_fi.uri);
+       de->de_fi.uri = uri;
+       de->de_dirty = 0;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/dirent.c (from rev 20388, 
gnunet-fuse/dirent.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/dirent.c                         (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/dirent.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,385 @@
+/*
+ * dirent.c - stuff for directory entries
+ *
+ * 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 <glib.h>
+#include <string.h>
+#include <errno.h>
+#include "gnfs.h"
+
+GHashTable *path_hash;
+struct GNUNET_Semaphore *path_sema;
+
+/*
+ * Reference a dirent, call gn_dirent_put when finished
+ */
+void gn_dirent_ref(struct dirent *de)
+{
+       GNUNET_mutex_lock(de->de_refs_mutex);
+       de->de_refs++;
+       GNUNET_mutex_unlock(de->de_refs_mutex);
+}
+
+/*
+ * Reference a dirent from the cache, call gn_dirent_put when finished with it
+ */
+struct dirent *gn_dirent_get(const gchar *path)
+{
+       struct dirent *de;
+
+       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
+               return NULL;
+       de = g_hash_table_lookup(path_hash, path);
+       if(de != NULL)
+               gn_dirent_ref(de);
+       GNUNET_semaphore_up(path_sema);
+       return de;
+}
+
+/*
+ * Release a reference to a dirent
+ */
+void gn_dirent_put(struct dirent *de)
+{
+       GNUNET_mutex_lock(de->de_refs_mutex);
+       de->de_refs--;
+       if(de->de_refs >= 1)
+       {
+               GNUNET_mutex_unlock(de->de_refs_mutex);
+               return;
+       }
+       GNUNET_mutex_unlock(de->de_refs_mutex);
+       GNUNET_mutex_destroy(de->de_path_mutex);
+       GNUNET_free(de->de_path);
+       GNUNET_mutex_destroy(de->de_refs_mutex);
+       GNUNET_semaphore_destroy(de->de_sema);
+       if(de->de_fi.uri != NULL)
+               GNUNET_ECRS_uri_destroy(de->de_fi.uri);
+       if(de->de_fi.meta != NULL)
+               GNUNET_meta_data_destroy(de->de_fi.meta);
+       if(de->de_type == DE_DIR)
+       {
+               if(de->de_cached)
+               {
+                       g_hash_table_destroy(de->de_dir_hash);
+               }
+       }
+       else
+       {
+               if(de->de_cached)
+               {
+                       close(de->de_fd);
+                       unlink(de->de_filename);
+                       GNUNET_free(de->de_filename);
+               }
+       }
+       GNUNET_free(de);
+}
+
+char *gn_dirent_path_get(struct dirent *de)
+{
+       char *ret;
+
+       GNUNET_mutex_lock(de->de_path_mutex);
+       ret = GNUNET_strdup(de->de_path);
+       GNUNET_mutex_unlock(de->de_path_mutex);
+       return ret;
+}
+
+/*
+ * DON'T call this if the dirent is ref'd by a hash
+ */
+void gn_dirent_path_set(struct dirent *de, const char *path)
+{
+       GNUNET_mutex_lock(de->de_path_mutex);
+       GNUNET_free(de->de_path);
+       de->de_path = GNUNET_strdup(path);
+       de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+       GNUNET_mutex_unlock(de->de_path_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 = GNUNET_semaphore_create(1);
+}
+
+/*
+ * Create a new dirent with a reference, path and uri are copied
+ */
+struct dirent *gn_dirent_new(const gchar *path, struct GNUNET_ECRS_URI *uri,
+       struct GNUNET_MetaData *meta, gchar type)
+{
+       struct dirent *de;
+
+       de = GNUNET_malloc(sizeof(*de));
+       de->de_path_mutex = GNUNET_mutex_create(0);
+       de->de_path = GNUNET_strdup(path);
+       de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+       de->de_refs_mutex = GNUNET_mutex_create(0);
+       de->de_refs = 1;
+       de->de_type = type;
+       de->de_sema = GNUNET_semaphore_create(1);
+       if(uri != NULL)
+       {
+               de->de_dirty = 0;
+               de->de_cached = 0;
+               de->de_fi.uri = GNUNET_ECRS_uri_duplicate(uri);
+       }
+       else
+       {
+               de->de_dirty = 1;
+               de->de_cached = 1;
+               if(type == DE_FILE)
+               {
+                       char filename[] = GN_MKSTEMP_FILE;
+
+                       de->de_fd = mkstemp(filename);
+                       de->de_filename = GNUNET_strdup(filename);
+               }
+               else
+               {
+                       de->de_dir_hash = g_hash_table_new_full(g_str_hash,
+                               g_str_equal, NULL,
+                               (GDestroyNotify)gn_dirent_put);
+               }
+       }
+       if(meta == NULL)
+               de->de_fi.meta = GNUNET_meta_data_create();
+       else
+               de->de_fi.meta = GNUNET_meta_data_duplicate(meta);
+       return de;
+}
+
+/*
+ * Add a dirent to the cache
+ */
+void gn_dirent_cache_insert(struct dirent *de)
+{
+       /* TODO: Here we need to see if the cache has gotten too big and empty
+        * it.
+        * XXX: But what about diry entries?? */
+       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
+               return;
+       GNUNET_mutex_lock(de->de_path_mutex);
+       GNUNET_GE_ASSERT(ectx, !g_hash_table_lookup(path_hash, de->de_path));
+       g_hash_table_replace(path_hash, de->de_path, de);
+       GNUNET_mutex_unlock(de->de_path_mutex);
+       gn_dirent_ref(de);
+       GNUNET_semaphore_up(path_sema);
+}
+
+/*
+ * Remove a dirent from the cache
+ */
+void gn_dirent_cache_remove(struct dirent *de)
+{
+       if(GNUNET_semaphore_down(path_sema, GNUNET_YES) == GNUNET_SYSERR)
+               return;
+       /* This is safe because we still hold a ref */
+       GNUNET_mutex_lock(de->de_path_mutex);
+       g_hash_table_remove(path_hash, de->de_path);
+       GNUNET_mutex_unlock(de->de_path_mutex);
+       GNUNET_semaphore_up(path_sema);
+}
+
+/*
+ * Call 'cb' for each element in 'path', treats the empty string as "/"
+ */
+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, *filename;
+
+       /* Start de off at the root */
+       de = root_de;
+       gn_dirent_ref(de);
+
+       /* Allocate partial path buffer */
+       len = strlen(path);
+       ppath = GNUNET_malloc(len + 1);
+       plen = 0;
+
+       /* 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 */
+               filename = &ppath[plen + 1];
+
+               /* Cat next path component */
+               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 */
+               next_de = gn_dirent_get(ppath);
+
+               /* If we found it then continue */
+               if(next_de != NULL)
+               {
+                       gn_dirent_put(de);
+                       de = next_de;
+                       continue;
+               }
+
+               /* We need to find it by listing its parent directory, de */
+               next_de = gn_directory_find(de, filename);
+
+               /* Not found? */
+               if(next_de == NULL)
+               {
+                       gn_dirent_put(de);
+                       de = NULL;
+                       break;
+               }
+
+               /* Continue to the next path element */
+               gn_dirent_put(de);
+               de = next_de;
+       }
+
+       /* Done */
+       GNUNET_free(ppath);
+       if(de == NULL)
+               return -1;
+       gn_dirent_put(de);
+       return 0;
+}
+
+static gboolean dirent_find_callback(struct dirent *de, void *data)
+{
+       struct dirent **d = 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 = NULL;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: called for '%s'\n", __FUNCTION__, path);
+       if(gn_path_foreach(path, dirent_find_callback, &de) == -1)
+       {
+               if(de != NULL)
+                       gn_dirent_put(de);
+               return NULL;
+       }
+       return de;
+}
+
+static gboolean lock_path_callback(struct dirent *de, void *data)
+{
+       struct dirent **detmp = data;
+
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == -1)
+               return 1;
+       gn_dirent_ref(de);
+       *detmp = de;
+       return 0;
+}
+
+/*
+ * Locks each element in a path.
+ */
+int gn_lock_path(struct dirent *de)
+{
+       struct dirent *detmp = NULL;
+       char *path;
+
+       path = gn_dirent_path_get(de);
+       if(gn_path_foreach(path, lock_path_callback, &detmp) == -1)
+       {
+               GNUNET_free(path);
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: failed!\n", __FUNCTION__);
+               /* Back out all the locks we aquired */
+               if(detmp != NULL)
+                       gn_unlock_path(detmp, GN_UNLOCK_CLEAN);
+               return -1;
+       }
+       GNUNET_free(path);
+       return 0;
+}
+
+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;
+       GNUNET_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;
+       char *path;
+
+       d.dirty = dirty;
+       d.de = de;
+       path = gn_dirent_path_get(de);
+       if(gn_path_foreach(path, unlock_path_callback, &d) == -1)
+       {
+               GNUNET_free(path);
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: failed!\n", __FUNCTION__);
+               return -1;
+       }
+       GNUNET_free(path);
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/file.c (from rev 20388, gnunet-fuse/file.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/file.c                           (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/file.c   2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,126 @@
+/*
+ * file.c - operations on files
+ *
+ * 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 <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <GNUnet/gnunet_ecrs_lib.h>
+#include "gnfs.h"
+
+static int tt(void *cls)
+{
+       (void)cls;
+       if(closing)
+               return GNUNET_OK;
+       if(fuse_interrupted())
+               return GNUNET_SYSERR;
+       return GNUNET_OK;
+}
+
+static void upcb(unsigned long long totalBytes, 
+                unsigned long long completedBytes, GNUNET_CronTime eta,
+       void *closure)
+{
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       (void)closure;
+}
+
+static void dpcb(unsigned long long totalBytes,
+        unsigned long long completedBytes, GNUNET_CronTime eta,
+        unsigned long long lastBlockOffset, const char *lastBlock,
+        unsigned int lastBlockSize, void *cls)
+{
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       (void)lastBlockOffset;
+       (void)lastBlock;
+       (void)lastBlockSize;
+       (void)cls;
+}
+
+/*
+ * Download a file for writing, de_sema must be held.
+ */
+int gn_file_download_locked(struct dirent *de)
+{
+       char filename[] = GN_MKSTEMP_FILE;
+
+       /* We may already be cached */
+       if(de->de_cached)
+               return 0;
+
+       /* Do the download */
+       de->de_fd = mkstemp(filename);
+       if(de->de_fd == -1)
+       {
+               GNUNET_GE_LOG_STRERROR_FILE(ectx, GNUNET_GE_BULK | 
GNUNET_GE_DEVELOPER
+                       | GNUNET_GE_ERROR, "mkstemp", filename);
+               return -1;
+       }
+       de->de_filename = GNUNET_strdup(filename);
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: downloading '%s'\n", __FUNCTION__, de->de_filename);
+       if(GNUNET_ECRS_file_download(ectx, cfg, de->de_fi.uri, filename, 
anonymity,
+               dpcb, NULL, tt, NULL) == GNUNET_SYSERR)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: download failed\n", __FUNCTION__);
+               close(de->de_fd);
+               unlink(de->de_filename);
+               GNUNET_free(de->de_filename);
+               return -1;
+       }
+
+       /* Mark ourselves cached */
+       de->de_cached = 1;
+       return 0;
+}
+
+int gn_file_upload_locked(struct dirent *de)
+{
+       struct GNUNET_ECRS_URI *uri;
+
+       /* If we're not dirty then we're done */
+       if(!de->de_dirty)
+               return 0;
+
+       if(GNUNET_ECRS_file_upload(ectx, cfg, de->de_filename, GNUNET_NO, 
anonymity, priority,
+               -1, upcb, NULL, tt, NULL, &uri) == GNUNET_SYSERR)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_ERROR,
+                       "%s: upload failed\n", __FUNCTION__);
+               return -1;
+       }
+       if(de->de_fi.uri != NULL)
+               GNUNET_ECRS_uri_destroy(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);
+       GNUNET_free(de->de_filename);
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/getattr.c (from rev 20388, 
gnunet-fuse/getattr.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/getattr.c                                (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/getattr.c        2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,86 @@
+/*
+ * getattr.c - FUSE getattr 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 <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_getattr(const char *path, struct stat *stbuf)
+{
+       struct dirent *de;
+       int ret = 0;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* Check to see if this is a special file */
+       if(gn_exists_special_file(path))
+       {
+               memset(stbuf, 0, sizeof(*stbuf));
+               stbuf->st_mode = 0555 | S_IFREG;
+               stbuf->st_nlink = 1;
+               /* sysfs uses 4096 for variable sized files */
+               stbuf->st_size = 4096;
+               return 0;
+       }
+
+       /* Fill in dirent stat info */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_DEBUG,
+                       "%s: could not find path '%s'\n", __FUNCTION__, path);
+               return -ENOENT;
+       }
+
+       /* If it's a cached file just call stat */
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+       {
+               gn_dirent_put(de);
+               return -EIO;
+       }
+       if(de->de_cached && de->de_type == DE_FILE)
+       {
+               ret = stat(de->de_filename, stbuf);
+               if(ret == -1)
+               {
+                       ret = -errno;
+                       GNUNET_GE_LOG_STRERROR(ectx, GNUNET_GE_BULK | 
GNUNET_GE_USER | GNUNET_GE_ERROR,
+                               "stat");
+                       goto out;
+               }
+               goto out;
+       }
+
+       memset(stbuf, 0, sizeof(*stbuf));
+       stbuf->st_mode = 0777;
+       stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
+       stbuf->st_nlink = 1;
+       if(de->de_fi.uri != NULL)
+               stbuf->st_size = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
+       else
+               stbuf->st_size = 0;
+out:
+       GNUNET_semaphore_up(de->de_sema);
+       gn_dirent_put(de);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/main.c (from rev 20388, gnunet-fuse/main.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/main.c                           (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/main.c   2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,232 @@
+/*
+ * main.c - program start
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <glib.h>
+#include <fuse.h>
+#include <GNUnet/gnunet_directories.h>
+#include <GNUnet/gnunet_util.h>
+#include <GNUnet/gnunet_ecrs_lib.h>
+#include "gnfs.h"
+#include "gettext.h"
+
+struct GNUNET_GC_Configuration *cfg;
+struct GNUNET_GE_Context *ectx;
+static char *cfgFilename = GNUNET_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;
+
+/* 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;
+
+int getopt_configure_argv(GNUNET_CommandLineProcessorContext *ctx, void *scls,
+       const char *cmdLineOption, const char *value)
+{
+       (void)ctx;
+       (void)scls;
+       (void)cmdLineOption;
+
+       fuse_argv[fuse_argc] = (char *)value;
+       fuse_argc++;
+       fuse_argv[fuse_argc] = NULL;
+       return GNUNET_OK;
+}
+
+static struct fuse_operations fops =
+{
+       .getattr = gn_getattr,
+       .mknod = gn_mknod,
+       .mkdir = gn_mkdir,
+       .unlink = gn_unlink,
+       .rmdir = gn_rmdir,
+       .rename = gn_rename,
+       .truncate = gn_truncate,
+       .open = gn_open,
+       .read = gn_read,
+       .write = gn_write,
+       .release = gn_release,
+       .readdir = gn_readdir,
+       .utimens = gn_utimens,
+};
+
+static struct GNUNET_CommandLineOption gn_options[] =
+{
+        GNUNET_COMMAND_LINE_OPTION_HELP("GNUnet filesystem"),
+       GNUNET_COMMAND_LINE_OPTION_CFG_FILE(&cfgFilename), /* -c */
+       GNUNET_COMMAND_LINE_OPTION_LOGGING, /* -L */
+       { 'l', "logfile", "FILE", "set logfile name", 1,
+               &GNUNET_getopt_configure_set_string, &cfgLogfile },
+       { '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,
+               &getopt_configure_argv, NULL },
+       GNUNET_COMMAND_LINE_OPTION_END,
+};
+
+int main(int argc, char **argv)
+{
+       int i, ret;
+       struct GNUNET_ECRS_URI *uri;
+       char *buf;
+
+       /* Initialize fuse options */
+       fuse_argc = 1;
+       fuse_argv = GNUNET_malloc(sizeof(char *) * argc);
+       fuse_argv[0] = argv[0];
+       fuse_argv[1] = NULL;
+
+       /* Parse gnunet options */
+       i = GNUNET_init(argc, argv,
+               "gnunet-fuse [OPTIONS] <URI FILE> <MOUNT-POINT>",
+               &cfgFilename, gn_options, &ectx, &cfg);
+       if(i == -1)
+       {
+               ret = -1;
+               goto quit;
+       }
+
+       /* Set up log file */
+       GNUNET_disk_directory_create_for_file(ectx, cfgLogfile);
+       ectx = GNUNET_GE_create_context_logfile(ectx, GNUNET_GE_ALL, 
cfgLogfile, NULL, GNUNET_YES, 0);
+       GNUNET_GE_setDefaultContext(ectx);
+
+       /* There should be exactly two extra arguments */
+       if(i + 2 != argc)
+       {
+               printf("You must specify a URI to mount and mountpoint\n");
+               ret = -1;
+               goto quit;
+       }
+
+       /* Set URI as our root directory entry */
+       gn_dirent_cache_init();
+       if(GNUNET_disk_file_test(ectx, argv[i]) == GNUNET_YES)
+       {
+               unsigned long long len;
+               char *uribuf;
+
+               root_fd = GNUNET_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(GNUNET_disk_file_size(ectx, argv[i], &len, GNUNET_YES) == 
GNUNET_SYSERR)
+               {
+                       printf("Unable to determine URI file size\n");
+                       ret = -1;
+                       goto out_close_root;
+               }
+               uribuf = GNUNET_malloc(len + 1);
+               read(root_fd, uribuf, len);
+               uribuf[len] = '\0';
+               uri = GNUNET_ECRS_string_to_uri(ectx, uribuf);
+               GNUNET_free(uribuf);
+               if(uri == NULL)
+               {
+                       printf("URI cannot be parsed\n");
+                       ret = -1;
+                       goto out_close_root;
+               }
+               if(!GNUNET_ECRS_uri_test_chk(uri))
+               {
+                       struct GNUNET_ECRS_URI *new_uri;
+
+                       new_uri = GNUNET_ECRS_uri_get_content_uri_from_loc(uri);
+                       if(new_uri == NULL)
+                       {
+                               printf("URI cannot be mounted\n");
+                               ret = -1;
+                               goto out_close_root;
+                       }
+                       GNUNET_ECRS_uri_destroy(uri);
+                       uri = new_uri;
+               }
+               root_de = gn_dirent_new(G_DIR_SEPARATOR_S, uri, NULL, DE_DIR);
+               GNUNET_ECRS_uri_destroy(uri);
+       }
+       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 = GNUNET_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 = GNUNET_realloc(fuse_argv, sizeof(char *) * (fuse_argc + 2));
+       fuse_argv[fuse_argc] = argv[i + 1];
+       fuse_argc++;
+       fuse_argv[fuse_argc] = NULL;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | GNUNET_GE_DEBUG, 
"calling fuse_main\n");
+       ret = fuse_main(fuse_argc, fuse_argv, &fops, NULL);
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | GNUNET_GE_DEBUG, 
"fuse_main returned\n");
+
+       /* Save root uri */
+       closing = 1;
+       buf = gn_get_special_file(G_DIR_SEPARATOR_S URI_FILE);
+       if(buf != NULL)
+       {
+               ftruncate(root_fd, 0);
+               lseek(root_fd, SEEK_SET, 0);
+               write(root_fd, buf, strlen(buf));
+               GNUNET_free(buf);
+       }
+out_close_root:
+       GNUNET_disk_file_close(ectx, argv[i], root_fd);
+quit:
+       GNUNET_free(fuse_argv);
+       GNUNET_fini(ectx, cfg);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/mkdir.c (from rev 20388, gnunet-fuse/mkdir.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/mkdir.c                          (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/mkdir.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,71 @@
+/*
+ * mkdir.c - FUSE mkdir 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_mkdir(const char *path, mode_t mode)
+{
+       struct dirent *de, *newde;
+       struct GNUNET_MetaData *meta;
+       char *parent, *file;
+       int ret;
+
+       (void)mode;
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EEXIST;
+
+       /* Check for existing file */
+       de = gn_dirent_find(path);
+       if(de != NULL)
+       {
+               gn_dirent_put(de);
+               return -EEXIST;
+       }
+
+       /* Create new directory */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       if(de == NULL)
+       {
+               GNUNET_free(parent);
+               return -ENOENT;
+       }
+       meta = GNUNET_meta_data_create();
+       GNUNET_meta_data_insert(meta, EXTRACTOR_FILENAME, file);
+       GNUNET_meta_data_insert(meta, EXTRACTOR_MIMETYPE, 
GNUNET_DIRECTORY_MIME);
+       newde = gn_dirent_new(path, NULL, meta, DE_DIR);
+       GNUNET_meta_data_destroy(meta);
+       ret = gn_directory_insert(de, newde);
+       gn_dirent_put(de);
+       gn_dirent_put(newde);
+       GNUNET_free(parent);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/mknod.c (from rev 20388, gnunet-fuse/mknod.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/mknod.c                          (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/mknod.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,77 @@
+/*
+ * mknod.c - FUSE mknod 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+       struct dirent *de, *newde;
+       struct GNUNET_ECRS_URI *uri;
+       struct GNUNET_MetaData *meta;
+       char *parent, *file;
+       int ret;
+
+       (void)rdev;
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* We only support regular files */
+       if(!S_ISREG(mode))
+               return -ENOTSUP;
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EEXIST;
+
+       /* Check for existing file */
+       de = gn_dirent_find(path);
+       if(de != NULL)
+       {
+               gn_dirent_put(de);
+               return -EEXIST;
+       }
+
+       /* Create new file */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       if(de == NULL)
+       {
+               GNUNET_free(parent);
+               return -ENOENT;
+       }
+       uri = GNUNET_ECRS_string_to_uri(ectx, GN_EMPTY_FILE_URI);
+       meta = GNUNET_meta_data_create();
+       GNUNET_meta_data_insert(meta, EXTRACTOR_FILENAME, file);
+       GNUNET_free(parent);
+       newde = gn_dirent_new(path, uri, meta, DE_FILE);
+       GNUNET_meta_data_destroy(meta);
+       GNUNET_ECRS_uri_destroy(uri);
+       ret = gn_directory_insert(de, newde);
+       gn_dirent_put(de);
+       gn_dirent_put(newde);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/open.c (from rev 20388, gnunet-fuse/open.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/open.c                           (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/open.c   2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,60 @@
+/*
+ * open.c - FUSE open 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_open(const char *path, struct fuse_file_info *fi)
+{
+       struct dirent *de;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+       
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+       {
+               if(fi->flags & O_WRONLY)
+                       return -EACCES;
+               if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+                       return -EEXIST;
+               return 0;
+       }
+
+       /* Check for existing file */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+               return -ENOENT;
+       if(de->de_type != DE_FILE)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: not a file\n", __FUNCTION__);
+               gn_dirent_put(de);
+               return -ENOENT;
+       }
+       gn_dirent_put(de);
+       if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               return -EEXIST;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/read.c (from rev 20388, gnunet-fuse/read.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/read.c                           (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/read.c   2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,168 @@
+/*
+ * read.c - FUSE read 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
+ */
+
+#define _XOPEN_SOURCE 500
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+struct read_data
+{
+       char *buf;
+       guint size;
+       guint64 offset;
+};
+
+static void dpcb(unsigned long long totalBytes,
+       unsigned long long completedBytes, GNUNET_CronTime eta,
+       unsigned long long lastBlockOffset, const char *lastBlock,
+       unsigned int lastBlockSize, void *cls)
+{
+       struct read_data *d = cls;
+       guint64 block_end = lastBlockOffset + lastBlockSize;
+       guint64 buf_end = d->offset + d->size;
+
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+
+       /* Check if this block is entirely before the buffer */
+       if(block_end < d->offset)
+               return;
+
+       /* Check if this block is entirely after the buffer */
+       if(lastBlockOffset > buf_end)
+               return;
+
+       /* Chop off residue at beginning of block */
+       if(lastBlockOffset < d->offset)
+       {
+               lastBlock += d->offset - lastBlockOffset;
+               lastBlockSize -= d->offset - lastBlockOffset;
+               lastBlockOffset = d->offset;
+       }
+       /* Chop off residue at end of block */
+       if(block_end > buf_end)
+       {
+               lastBlockSize -= block_end - buf_end;
+       }
+       memcpy(d->buf + (lastBlockOffset - d->offset), lastBlock,
+               lastBlockSize);
+}
+
+static int tt(void *cls)
+{
+       (void)cls;
+       return fuse_interrupted() ? GNUNET_SYSERR : GNUNET_OK;
+}
+
+int gn_read(const char *path, char *buf, size_t size, off_t offset,
+       struct fuse_file_info *fi)
+{
+       struct dirent *de;
+       struct read_data d;
+       char *special;
+       int ret;
+       ssize_t slen;
+       guint64 len;
+
+       (void)fi;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: called for '%s' %u bytes %lld offset\n", __FUNCTION__,
+               path, size, offset);
+
+       /* Check for special file */
+       special = gn_get_special_file(path);
+       if(special != NULL)
+       {
+               slen = strlen(special);
+               if(offset >= slen)
+               {
+                       GNUNET_free(special);
+                       return 0;
+               }
+               if( ((ssize_t) (offset + size)) > slen)
+               {
+                       size = slen - offset;
+               }
+               memcpy(buf, special + offset, size);
+               GNUNET_free(special);
+               return size;
+       }
+
+       /* Lookup dirent for path */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: file not found\n", __FUNCTION__);
+               return -ENOENT;
+       }
+       if(de->de_type != DE_FILE)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: not a file\n", __FUNCTION__);
+               size = -ENOENT;
+               goto out;
+       }
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+       {
+               size = -EIO;
+               goto out;
+       }
+       if(de->de_cached)
+       {
+               slen = pread(de->de_fd, buf, size, offset);
+               if(slen == -1)
+                       size = -errno;
+               else
+                       size = slen;
+               goto out_sema_up;
+       }
+       len = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
+       if((guint64)offset >= len)
+       {
+               size = 0;
+               goto out_sema_up;
+       }
+       if((guint64)offset + size > len)
+       {
+               size = len - offset;
+       }
+       d.buf = buf;
+       d.size = size;
+       d.offset = offset;
+       ret = GNUNET_ECRS_file_download_partial(ectx, cfg, de->de_fi.uri, 
"/dev/null",
+               offset, size, anonymity, GNUNET_YES, dpcb, &d, tt, NULL);
+       if(ret != GNUNET_OK)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_ERROR,
+                       "%s: failed to download file\n", __FUNCTION__);
+               size = -ENODATA;
+       }
+out_sema_up:
+       GNUNET_semaphore_up(de->de_sema);
+out:
+       gn_dirent_put(de);
+       return size;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/readdir.c (from rev 20388, 
gnunet-fuse/readdir.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/readdir.c                                (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/readdir.c        2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,113 @@
+/*
+ * readdir.c - FUSE readdir 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
+ */
+
+#define _LARGEFILE64_SOURCE
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <fuse.h>
+#include <GNUnet/gnunet_ecrs_lib.h>
+#include "gnfs.h"
+
+struct readdir_callback_data
+{
+       fuse_fill_dir_t filler;
+       void *buf;
+       const char *prefix;
+};
+
+static int readdir_callback(struct dirent *de, void *data)
+{
+       struct readdir_callback_data *d = data;
+
+       (void)de;
+
+       if(d->prefix != NULL)
+       {
+               char *buf = GNUNET_malloc(strlen(d->prefix) + 
strlen(de->de_basename)
+                       + 1);
+
+               sprintf(buf, "%s%s", d->prefix, de->de_basename);
+               d->filler(d->buf, buf, NULL, 0);
+               GNUNET_free(buf);
+       }
+       else
+       {
+               d->filler(d->buf, de->de_basename, NULL, 0);
+       }
+       return GNUNET_OK;
+}
+
+int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+       off_t offset, struct fuse_file_info *fi)
+{
+       struct dirent *de;
+       int ret = 0;
+       struct readdir_callback_data d;
+
+       (void)offset;
+       (void)fi;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "readdir for '%s'\n",
+               path);
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "readdir: file not found\n");
+               return -ENOENT;
+       }
+       if(de->de_type != DE_DIR)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "readdir: not a directory\n");
+               gn_dirent_put(de);
+               ret = -ENOENT;
+               goto out;
+       }
+       filler(buf, ".", NULL, 0);
+       filler(buf, "..", NULL, 0);
+       if(uri_files)
+       {
+               filler(buf, URI_FILE, NULL, 0);
+               d.filler = filler;
+               d.buf = buf;
+               d.prefix = ".uri.";
+               ret = gn_directory_foreach(de, readdir_callback, &d);
+               if(ret == -1)
+               {
+                       ret = -ENOENT;
+                       goto out;
+               }
+       }
+       d.filler = filler;
+       d.buf = buf;
+       d.prefix = NULL;
+       ret = gn_directory_foreach(de, readdir_callback, &d);
+       if(ret == -1)
+               ret = -ENOENT;
+out:
+       gn_dirent_put(de);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/release.c (from rev 20388, 
gnunet-fuse/release.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/release.c                                (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/release.c        2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,63 @@
+/*
+ * 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 <fuse.h>
+#include "gnfs.h"
+
+int gn_release(const char *path, struct fuse_file_info *fi)
+{
+       struct dirent *de;
+       int dirty = GN_UNLOCK_CLEAN;
+
+       (void)fi;
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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;
+
+       /* Un-dirty ourselfs */
+       if(gn_file_upload_locked(de) == 0)
+       {
+               /* Now we must mark every containing directory dirty */
+               dirty = GN_UNLOCK_ANCESTORS_DIRTY;
+       }
+
+       gn_unlock_path(de, dirty);
+       gn_dirent_put(de);
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/rename.c (from rev 20388, 
gnunet-fuse/rename.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/rename.c                         (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/rename.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,135 @@
+/*
+ * rename.c - FUSE rename 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+static gboolean rename_callback(struct dirent *de, void *data)
+{
+       int *empty = data;
+
+       (void)de;
+       *empty = 0;
+       return 1;
+}
+
+int gn_rename(const char *from, const char *to)
+{
+       struct dirent *from_de, *to_de, *from_parent_de, *to_parent_de;
+       char *from_parent, *from_file, *to_parent, *to_file;
+       int ret = 0, empty = 1;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: '%s' to '%s'\n",
+               __FUNCTION__, from, to);
+
+       /* Check for special file */
+       if(gn_exists_special_file(from) || gn_exists_special_file(to))
+               return -EACCES;
+
+       /* Make sure 'from' exists */
+       from_de = gn_dirent_find(from);
+       if(from_de == NULL)
+               return -ENOENT;
+
+       /* We need to check some things before we remove 'from' */
+       to_de = gn_dirent_find(to);
+       if(to_de != NULL)
+       {
+               if(from_de->de_type == DE_FILE && to_de->de_type == DE_DIR)
+               {
+                       ret = -EISDIR;
+                       goto out;
+               }
+               if(from_de->de_type == DE_DIR && to_de->de_type == DE_FILE)
+               {
+                       ret = -ENOTDIR;
+                       goto out;
+               }
+               if(to_de->de_type == DE_DIR)
+               {
+                       gn_directory_foreach(to_de, rename_callback, &empty);
+                       if(!empty)
+                       {
+                               ret = -ENOTEMPTY;
+                               goto out;
+                       }
+               }
+       }
+
+       /* Now we can remove the 'from' */
+       from_parent = gn_dirname(from, &from_file);
+       from_parent_de = gn_dirent_find(from_parent);
+       GNUNET_free(from_parent);
+       if(from_parent_de == NULL)
+       {
+               ret = -ENOENT;
+               goto out;
+       }
+       gn_directory_remove(from_parent_de, from_de);
+       gn_dirent_put(from_parent_de);
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: removed '%s'\n",
+               __FUNCTION__, from);
+
+       /* Modify our path */
+       gn_dirent_path_set(from_de, to);
+
+       /* Replace the 'to' */
+       to_parent = gn_dirname(to, &to_file);
+       to_parent_de = gn_dirent_find(to_parent);
+       GNUNET_free(to_parent);
+       if(to_parent_de == NULL)
+       {
+               ret = -EIO;
+               goto out;
+       }
+
+       /* We should have some kind of directory_remove_insert for atomicity */
+       if(to_de != NULL)
+       {
+               if(gn_directory_remove(to_parent_de, to_de) == -1)
+               {
+                       gn_dirent_put(to_parent_de);
+                       ret = -EIO;
+                       goto out;
+               }
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: removed '%s'\n", __FUNCTION__, to);
+       }
+       if(gn_directory_insert(to_parent_de, from_de) == -1)
+       {
+               gn_dirent_put(to_parent_de);
+               ret = -EIO;
+               goto out;
+       }
+       gn_dirent_put(to_parent_de);
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: inserted '%s'\n", __FUNCTION__, to);
+
+out:
+       if(to_de != NULL)
+               gn_dirent_put(to_de);
+       if(from_de != NULL)
+               gn_dirent_put(from_de);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/rmdir.c (from rev 20388, gnunet-fuse/rmdir.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/rmdir.c                          (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/rmdir.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,78 @@
+/*
+ * rmdir.c - FUSE rmdir 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+static gboolean rmdir_callback(struct dirent *de, void *data)
+{
+       int *empty = data;
+
+       (void)de;
+       *empty = 0;
+       return 1;
+}
+
+int gn_rmdir(const char *path)
+{
+       struct dirent *de, *dechild;
+       char *parent, *file;
+       int ret, empty = 1;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -ENOTDIR;
+
+       /* Check for existing file */
+       dechild = gn_dirent_find(path);
+       if(dechild == NULL)
+               return -ENOENT;
+
+       /* Can't rmdir a non-empty directory */
+       gn_directory_foreach(dechild, rmdir_callback, &empty);
+       if(!empty)
+       {
+               gn_dirent_put(dechild);
+               return -ENOTEMPTY;
+       }
+
+       /* Remove directory */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       GNUNET_free(parent);
+       if(de == NULL)
+       {
+               gn_dirent_put(dechild);
+               return -ENOENT;
+       }
+       ret = gn_directory_remove(de, dechild);
+       gn_dirent_put(dechild);
+       gn_dirent_put(de);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/special_file.c (from rev 20388, 
gnunet-fuse/special_file.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/special_file.c                           (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/special_file.c   2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,159 @@
+/*
+ * special_file.c - special file support (like .uri)
+ *
+ * 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 <string.h>
+#include <GNUnet/gnunet_util_string.h>
+#include <GNUnet/gnunet_ecrs_lib.h>
+#include "gnfs.h"
+
+char *gn_dirname(const char *path, char **file)
+{
+       char *parent, *slash;
+
+       parent = GNUNET_strdup(path);
+       slash = strrchr(parent, G_DIR_SEPARATOR);
+       if(slash != NULL)
+       {
+               slash[0] = '\0';
+               slash++;
+       }
+       if(file != NULL)
+               *file = slash;
+       return parent;
+}
+
+/* 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;
+
+       parent = gn_dirname(path, &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 = GNUNET_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);
+               GNUNET_free(actual_file);
+               if(de == NULL)
+                       goto out;
+               gn_dirent_put(de);
+               ret = 1;
+       }
+out:
+       GNUNET_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;
+       char *buf = NULL, *file, *parent;
+
+       parent = gn_dirname(path, &file);
+
+       /* Check for special file name */
+       if(strcmp(file, URI_FILE) == 0)
+       {
+               /* Return URI of the 'current' directory */
+               de = gn_dirent_find(parent);
+               if(de == NULL)
+                       goto out;
+               if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == 
GNUNET_SYSERR)
+               {
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               if(de->de_dirty)
+               {
+                       if(gn_directory_upload_locked(de) == -1)
+                       {
+                               GNUNET_semaphore_up(de->de_sema);
+                               gn_dirent_put(de);
+                               goto out;
+                       }
+               }
+               buf = GNUNET_ECRS_uri_to_string(de->de_fi.uri);
+               GNUNET_semaphore_up(de->de_sema);
+               gn_dirent_put(de);
+               buf = GNUNET_realloc(buf, strlen(buf) + 2);
+               strcat(buf, "\n");
+       }
+       else if(strncmp(file, URI_FILE ".", URI_LEN + 1) == 0)
+       {
+               char *actual_file = GNUNET_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);
+               GNUNET_free(actual_file);
+               if(de == NULL)
+                       goto out;
+               if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == 
GNUNET_SYSERR)
+               {
+                       gn_dirent_put(de);
+                       goto out;
+               }
+               if(de->de_dirty)
+               {
+                       if(de->de_type == DE_DIR)
+                       {
+                               if(gn_directory_upload_locked(de) == -1)
+                               {
+                                       GNUNET_semaphore_up(de->de_sema);
+                                       gn_dirent_put(de);
+                                       goto out;
+                               }
+                       }
+                       else
+                       {
+                               if(de->de_fi.uri == NULL)
+                               {
+                                       GNUNET_semaphore_up(de->de_sema);
+                                       gn_dirent_put(de);
+                                       goto out;
+                               }
+                       }
+               }
+               buf = GNUNET_ECRS_uri_to_string(de->de_fi.uri);
+               GNUNET_semaphore_up(de->de_sema);
+               gn_dirent_put(de);
+               buf = GNUNET_realloc(buf, strlen(buf) + 2);
+               strcat(buf, "\n");
+       }
+out:
+       GNUNET_free(parent);
+       return buf;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/truncate.c (from rev 20388, 
gnunet-fuse/truncate.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/truncate.c                               (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/truncate.c       2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,90 @@
+/*
+ * truncate.c - FUSE truncate 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 <errno.h>
+#include <unistd.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_truncate(const char *path, off_t size)
+{
+       struct dirent *de;
+       int ret = 0, dirty = GN_UNLOCK_CLEAN;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: called for '%s' %lld bytes\n", __FUNCTION__, path, size);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EACCES;
+
+       /* Lookup dirent for path */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: file not found\n", __FUNCTION__);
+               return -ENOENT;
+       }
+       if(de->de_type != DE_FILE)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: not a file\n", __FUNCTION__);
+               ret = -EISDIR;
+               goto out;
+       }
+
+       /* Lock our path */
+       if(gn_lock_path(de) == -1)
+       {
+               ret = -EIO;
+               goto out;
+       }
+       if(!de->de_cached)
+       {
+               if(gn_file_download_locked(de) == -1)
+               {
+                       ret = -EIO;
+                       goto out_unlock;
+               }
+       }
+
+       /* Perform truncate */
+       ret = ftruncate(de->de_fd, size);
+       if(ret == -1)
+       {
+               ret = -errno;
+               goto out_unlock;
+       }
+
+       /* Mark us dirty */
+       de->de_dirty = 1;
+
+       /* Then un-mark us dirty */
+       if(gn_file_upload_locked(de) == 0)
+       {
+               dirty = GN_UNLOCK_ANCESTORS_DIRTY;
+       }
+out_unlock:
+       gn_unlock_path(de, GN_UNLOCK_ANCESTORS_DIRTY);
+out:
+       gn_dirent_put(de);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/unlink.c (from rev 20388, 
gnunet-fuse/unlink.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/unlink.c                         (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/unlink.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,68 @@
+/*
+ * unlink.c - FUSE unlink 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_unlink(const char *path)
+{
+       struct dirent *de, *dechild;
+       char *parent, *file;
+       int ret;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EPERM;
+
+       /* Check for existing file */
+       dechild = gn_dirent_find(path);
+       if(dechild == NULL)
+               return -ENOENT;
+       
+       /* Can't unlink a directory */
+       if(dechild->de_type != DE_FILE)
+       {
+               gn_dirent_put(dechild);
+               return -EPERM;
+       }
+
+       /* Remove file from parent dir */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       GNUNET_free(parent);
+       if(de == NULL)
+       {
+               gn_dirent_put(dechild);
+               return -ENOENT;
+       }
+       ret = gn_directory_remove(de, dechild);
+       gn_dirent_put(dechild);
+       gn_dirent_put(de);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/utimens.c (from rev 20388, 
gnunet-fuse/utimens.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/utimens.c                                (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/utimens.c        2012-03-09 08:38:54 UTC (rev 
20389)
@@ -0,0 +1,72 @@
+/*
+ * utimens.c - FUSE utimens 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
+ */
+
+#define _GNU_SOURCE
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_utimens(const char *path, const struct timespec ts[2])
+{
+       struct dirent *de;
+       struct timeval tv[2];
+       int ret = 0;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* Check to see if this is a special file */
+       if(gn_exists_special_file(path))
+               return -EACCES;
+
+       /* Get file or dir */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+               return -ENOENT;
+
+       /* If it's a cached file just call utime */
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+       {
+               gn_dirent_put(de);
+               return -EIO;
+       }
+       if(de->de_cached && de->de_type == DE_FILE)
+       {
+               TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
+               TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
+               ret = utimes(path, tv);
+               if(ret == -1)
+               {
+                       ret = -errno;
+                       GNUNET_GE_LOG_STRERROR(ectx, GNUNET_GE_BULK | 
GNUNET_GE_USER | GNUNET_GE_ERROR,
+                               "utimes");
+                       goto out;
+               }
+               goto out;
+       }
+
+       /* For now we do nothing otherwise */
+out:
+       GNUNET_semaphore_up(de->de_sema);
+       gn_dirent_put(de);
+       return ret;
+}

Copied: gnunet-fuse/gnunet-fuse-v8/write.c (from rev 20388, gnunet-fuse/write.c)
===================================================================
--- gnunet-fuse/gnunet-fuse-v8/write.c                          (rev 0)
+++ gnunet-fuse/gnunet-fuse-v8/write.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -0,0 +1,88 @@
+/*
+ * write.c - FUSE write 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
+ */
+
+#define _XOPEN_SOURCE 500
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_write(const char *path, const char *buf, size_t size, off_t offset,
+       struct fuse_file_info *fi)
+{
+       struct dirent *de;
+       ssize_t slen;
+
+       (void)fi;
+
+       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+               "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EACCES;
+
+       /* Lookup dirent for path */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: file not found\n", __FUNCTION__);
+               return -ENOENT;
+       }
+       if(de->de_type != DE_FILE)
+       {
+               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
+                       "%s: not a file\n", __FUNCTION__);
+               size = -ENOENT;
+               goto out;
+       }
+
+       /* We must be cached */
+       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
+       {
+               size = -EIO;
+               goto out;
+       }
+       if(!de->de_cached)
+       {
+               if(gn_file_download_locked(de) == -1)
+               {
+                       size = -EIO;
+                       goto out_unlock;
+               }
+       }
+
+       /* Perform write on temp file */
+       slen = pwrite(de->de_fd, buf, size, offset);
+       if(slen == -1)
+               size = -errno;
+       else
+               size = slen;
+
+       /* Mark us dirty */
+       de->de_dirty = 1;
+out_unlock:
+       GNUNET_semaphore_up(de->de_sema);
+out:
+       gn_dirent_put(de);
+       return size;
+}

Deleted: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c  2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/main.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,232 +0,0 @@
-/*
- * main.c - program start
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <glib.h>
-#include <fuse.h>
-#include <GNUnet/gnunet_directories.h>
-#include <GNUnet/gnunet_util.h>
-#include <GNUnet/gnunet_ecrs_lib.h>
-#include "gnfs.h"
-#include "gettext.h"
-
-struct GNUNET_GC_Configuration *cfg;
-struct GNUNET_GE_Context *ectx;
-static char *cfgFilename = GNUNET_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;
-
-/* 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;
-
-int getopt_configure_argv(GNUNET_CommandLineProcessorContext *ctx, void *scls,
-       const char *cmdLineOption, const char *value)
-{
-       (void)ctx;
-       (void)scls;
-       (void)cmdLineOption;
-
-       fuse_argv[fuse_argc] = (char *)value;
-       fuse_argc++;
-       fuse_argv[fuse_argc] = NULL;
-       return GNUNET_OK;
-}
-
-static struct fuse_operations fops =
-{
-       .getattr = gn_getattr,
-       .mknod = gn_mknod,
-       .mkdir = gn_mkdir,
-       .unlink = gn_unlink,
-       .rmdir = gn_rmdir,
-       .rename = gn_rename,
-       .truncate = gn_truncate,
-       .open = gn_open,
-       .read = gn_read,
-       .write = gn_write,
-       .release = gn_release,
-       .readdir = gn_readdir,
-       .utimens = gn_utimens,
-};
-
-static struct GNUNET_CommandLineOption gn_options[] =
-{
-        GNUNET_COMMAND_LINE_OPTION_HELP("GNUnet filesystem"),
-       GNUNET_COMMAND_LINE_OPTION_CFG_FILE(&cfgFilename), /* -c */
-       GNUNET_COMMAND_LINE_OPTION_LOGGING, /* -L */
-       { 'l', "logfile", "FILE", "set logfile name", 1,
-               &GNUNET_getopt_configure_set_string, &cfgLogfile },
-       { '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,
-               &getopt_configure_argv, NULL },
-       GNUNET_COMMAND_LINE_OPTION_END,
-};
-
-int main(int argc, char **argv)
-{
-       int i, ret;
-       struct GNUNET_ECRS_URI *uri;
-       char *buf;
-
-       /* Initialize fuse options */
-       fuse_argc = 1;
-       fuse_argv = GNUNET_malloc(sizeof(char *) * argc);
-       fuse_argv[0] = argv[0];
-       fuse_argv[1] = NULL;
-
-       /* Parse gnunet options */
-       i = GNUNET_init(argc, argv,
-               "gnunet-fuse [OPTIONS] <URI FILE> <MOUNT-POINT>",
-               &cfgFilename, gn_options, &ectx, &cfg);
-       if(i == -1)
-       {
-               ret = -1;
-               goto quit;
-       }
-
-       /* Set up log file */
-       GNUNET_disk_directory_create_for_file(ectx, cfgLogfile);
-       ectx = GNUNET_GE_create_context_logfile(ectx, GNUNET_GE_ALL, 
cfgLogfile, NULL, GNUNET_YES, 0);
-       GNUNET_GE_setDefaultContext(ectx);
-
-       /* There should be exactly two extra arguments */
-       if(i + 2 != argc)
-       {
-               printf("You must specify a URI to mount and mountpoint\n");
-               ret = -1;
-               goto quit;
-       }
-
-       /* Set URI as our root directory entry */
-       gn_dirent_cache_init();
-       if(GNUNET_disk_file_test(ectx, argv[i]) == GNUNET_YES)
-       {
-               unsigned long long len;
-               char *uribuf;
-
-               root_fd = GNUNET_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(GNUNET_disk_file_size(ectx, argv[i], &len, GNUNET_YES) == 
GNUNET_SYSERR)
-               {
-                       printf("Unable to determine URI file size\n");
-                       ret = -1;
-                       goto out_close_root;
-               }
-               uribuf = GNUNET_malloc(len + 1);
-               read(root_fd, uribuf, len);
-               uribuf[len] = '\0';
-               uri = GNUNET_ECRS_string_to_uri(ectx, uribuf);
-               GNUNET_free(uribuf);
-               if(uri == NULL)
-               {
-                       printf("URI cannot be parsed\n");
-                       ret = -1;
-                       goto out_close_root;
-               }
-               if(!GNUNET_ECRS_uri_test_chk(uri))
-               {
-                       struct GNUNET_ECRS_URI *new_uri;
-
-                       new_uri = GNUNET_ECRS_uri_get_content_uri_from_loc(uri);
-                       if(new_uri == NULL)
-                       {
-                               printf("URI cannot be mounted\n");
-                               ret = -1;
-                               goto out_close_root;
-                       }
-                       GNUNET_ECRS_uri_destroy(uri);
-                       uri = new_uri;
-               }
-               root_de = gn_dirent_new(G_DIR_SEPARATOR_S, uri, NULL, DE_DIR);
-               GNUNET_ECRS_uri_destroy(uri);
-       }
-       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 = GNUNET_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 = GNUNET_realloc(fuse_argv, sizeof(char *) * (fuse_argc + 2));
-       fuse_argv[fuse_argc] = argv[i + 1];
-       fuse_argc++;
-       fuse_argv[fuse_argc] = NULL;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | GNUNET_GE_DEBUG, 
"calling fuse_main\n");
-       ret = fuse_main(fuse_argc, fuse_argv, &fops, NULL);
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | GNUNET_GE_DEBUG, 
"fuse_main returned\n");
-
-       /* Save root uri */
-       closing = 1;
-       buf = gn_get_special_file(G_DIR_SEPARATOR_S URI_FILE);
-       if(buf != NULL)
-       {
-               ftruncate(root_fd, 0);
-               lseek(root_fd, SEEK_SET, 0);
-               write(root_fd, buf, strlen(buf));
-               GNUNET_free(buf);
-       }
-out_close_root:
-       GNUNET_disk_file_close(ectx, argv[i], root_fd);
-quit:
-       GNUNET_free(fuse_argv);
-       GNUNET_fini(ectx, cfg);
-       return ret;
-}

Deleted: gnunet-fuse/mkdir.c
===================================================================
--- gnunet-fuse/mkdir.c 2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/mkdir.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,71 +0,0 @@
-/*
- * mkdir.c - FUSE mkdir 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_mkdir(const char *path, mode_t mode)
-{
-       struct dirent *de, *newde;
-       struct GNUNET_MetaData *meta;
-       char *parent, *file;
-       int ret;
-
-       (void)mode;
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -EEXIST;
-
-       /* Check for existing file */
-       de = gn_dirent_find(path);
-       if(de != NULL)
-       {
-               gn_dirent_put(de);
-               return -EEXIST;
-       }
-
-       /* Create new directory */
-       parent = gn_dirname(path, &file);
-       de = gn_dirent_find(parent);
-       if(de == NULL)
-       {
-               GNUNET_free(parent);
-               return -ENOENT;
-       }
-       meta = GNUNET_meta_data_create();
-       GNUNET_meta_data_insert(meta, EXTRACTOR_FILENAME, file);
-       GNUNET_meta_data_insert(meta, EXTRACTOR_MIMETYPE, 
GNUNET_DIRECTORY_MIME);
-       newde = gn_dirent_new(path, NULL, meta, DE_DIR);
-       GNUNET_meta_data_destroy(meta);
-       ret = gn_directory_insert(de, newde);
-       gn_dirent_put(de);
-       gn_dirent_put(newde);
-       GNUNET_free(parent);
-       if(ret == -1)
-               return -EIO;
-       return 0;
-}

Deleted: gnunet-fuse/mknod.c
===================================================================
--- gnunet-fuse/mknod.c 2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/mknod.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,77 +0,0 @@
-/*
- * mknod.c - FUSE mknod 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_mknod(const char *path, mode_t mode, dev_t rdev)
-{
-       struct dirent *de, *newde;
-       struct GNUNET_ECRS_URI *uri;
-       struct GNUNET_MetaData *meta;
-       char *parent, *file;
-       int ret;
-
-       (void)rdev;
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* We only support regular files */
-       if(!S_ISREG(mode))
-               return -ENOTSUP;
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -EEXIST;
-
-       /* Check for existing file */
-       de = gn_dirent_find(path);
-       if(de != NULL)
-       {
-               gn_dirent_put(de);
-               return -EEXIST;
-       }
-
-       /* Create new file */
-       parent = gn_dirname(path, &file);
-       de = gn_dirent_find(parent);
-       if(de == NULL)
-       {
-               GNUNET_free(parent);
-               return -ENOENT;
-       }
-       uri = GNUNET_ECRS_string_to_uri(ectx, GN_EMPTY_FILE_URI);
-       meta = GNUNET_meta_data_create();
-       GNUNET_meta_data_insert(meta, EXTRACTOR_FILENAME, file);
-       GNUNET_free(parent);
-       newde = gn_dirent_new(path, uri, meta, DE_FILE);
-       GNUNET_meta_data_destroy(meta);
-       GNUNET_ECRS_uri_destroy(uri);
-       ret = gn_directory_insert(de, newde);
-       gn_dirent_put(de);
-       gn_dirent_put(newde);
-       if(ret == -1)
-               return -EIO;
-       return 0;
-}

Deleted: gnunet-fuse/open.c
===================================================================
--- gnunet-fuse/open.c  2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/open.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,60 +0,0 @@
-/*
- * open.c - FUSE open 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_open(const char *path, struct fuse_file_info *fi)
-{
-       struct dirent *de;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-       
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-       {
-               if(fi->flags & O_WRONLY)
-                       return -EACCES;
-               if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-                       return -EEXIST;
-               return 0;
-       }
-
-       /* Check for existing file */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-               return -ENOENT;
-       if(de->de_type != DE_FILE)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: not a file\n", __FUNCTION__);
-               gn_dirent_put(de);
-               return -ENOENT;
-       }
-       gn_dirent_put(de);
-       if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-               return -EEXIST;
-       return 0;
-}

Deleted: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c  2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/read.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,168 +0,0 @@
-/*
- * read.c - FUSE read 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
- */
-
-#define _XOPEN_SOURCE 500
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-struct read_data
-{
-       char *buf;
-       guint size;
-       guint64 offset;
-};
-
-static void dpcb(unsigned long long totalBytes,
-       unsigned long long completedBytes, GNUNET_CronTime eta,
-       unsigned long long lastBlockOffset, const char *lastBlock,
-       unsigned int lastBlockSize, void *cls)
-{
-       struct read_data *d = cls;
-       guint64 block_end = lastBlockOffset + lastBlockSize;
-       guint64 buf_end = d->offset + d->size;
-
-       (void)totalBytes;
-       (void)completedBytes;
-       (void)eta;
-
-       /* Check if this block is entirely before the buffer */
-       if(block_end < d->offset)
-               return;
-
-       /* Check if this block is entirely after the buffer */
-       if(lastBlockOffset > buf_end)
-               return;
-
-       /* Chop off residue at beginning of block */
-       if(lastBlockOffset < d->offset)
-       {
-               lastBlock += d->offset - lastBlockOffset;
-               lastBlockSize -= d->offset - lastBlockOffset;
-               lastBlockOffset = d->offset;
-       }
-       /* Chop off residue at end of block */
-       if(block_end > buf_end)
-       {
-               lastBlockSize -= block_end - buf_end;
-       }
-       memcpy(d->buf + (lastBlockOffset - d->offset), lastBlock,
-               lastBlockSize);
-}
-
-static int tt(void *cls)
-{
-       (void)cls;
-       return fuse_interrupted() ? GNUNET_SYSERR : GNUNET_OK;
-}
-
-int gn_read(const char *path, char *buf, size_t size, off_t offset,
-       struct fuse_file_info *fi)
-{
-       struct dirent *de;
-       struct read_data d;
-       char *special;
-       int ret;
-       ssize_t slen;
-       guint64 len;
-
-       (void)fi;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: called for '%s' %u bytes %lld offset\n", __FUNCTION__,
-               path, size, offset);
-
-       /* Check for special file */
-       special = gn_get_special_file(path);
-       if(special != NULL)
-       {
-               slen = strlen(special);
-               if(offset >= slen)
-               {
-                       GNUNET_free(special);
-                       return 0;
-               }
-               if( ((ssize_t) (offset + size)) > slen)
-               {
-                       size = slen - offset;
-               }
-               memcpy(buf, special + offset, size);
-               GNUNET_free(special);
-               return size;
-       }
-
-       /* Lookup dirent for path */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: file not found\n", __FUNCTION__);
-               return -ENOENT;
-       }
-       if(de->de_type != DE_FILE)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: not a file\n", __FUNCTION__);
-               size = -ENOENT;
-               goto out;
-       }
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-       {
-               size = -EIO;
-               goto out;
-       }
-       if(de->de_cached)
-       {
-               slen = pread(de->de_fd, buf, size, offset);
-               if(slen == -1)
-                       size = -errno;
-               else
-                       size = slen;
-               goto out_sema_up;
-       }
-       len = GNUNET_ECRS_uri_get_file_size(de->de_fi.uri);
-       if((guint64)offset >= len)
-       {
-               size = 0;
-               goto out_sema_up;
-       }
-       if((guint64)offset + size > len)
-       {
-               size = len - offset;
-       }
-       d.buf = buf;
-       d.size = size;
-       d.offset = offset;
-       ret = GNUNET_ECRS_file_download_partial(ectx, cfg, de->de_fi.uri, 
"/dev/null",
-               offset, size, anonymity, GNUNET_YES, dpcb, &d, tt, NULL);
-       if(ret != GNUNET_OK)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_USER | 
GNUNET_GE_ERROR,
-                       "%s: failed to download file\n", __FUNCTION__);
-               size = -ENODATA;
-       }
-out_sema_up:
-       GNUNET_semaphore_up(de->de_sema);
-out:
-       gn_dirent_put(de);
-       return size;
-}

Deleted: gnunet-fuse/readdir.c
===================================================================
--- gnunet-fuse/readdir.c       2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/readdir.c       2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,113 +0,0 @@
-/*
- * readdir.c - FUSE readdir 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
- */
-
-#define _LARGEFILE64_SOURCE
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <glib.h>
-#include <fuse.h>
-#include <GNUnet/gnunet_ecrs_lib.h>
-#include "gnfs.h"
-
-struct readdir_callback_data
-{
-       fuse_fill_dir_t filler;
-       void *buf;
-       const char *prefix;
-};
-
-static int readdir_callback(struct dirent *de, void *data)
-{
-       struct readdir_callback_data *d = data;
-
-       (void)de;
-
-       if(d->prefix != NULL)
-       {
-               char *buf = GNUNET_malloc(strlen(d->prefix) + 
strlen(de->de_basename)
-                       + 1);
-
-               sprintf(buf, "%s%s", d->prefix, de->de_basename);
-               d->filler(d->buf, buf, NULL, 0);
-               GNUNET_free(buf);
-       }
-       else
-       {
-               d->filler(d->buf, de->de_basename, NULL, 0);
-       }
-       return GNUNET_OK;
-}
-
-int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-       off_t offset, struct fuse_file_info *fi)
-{
-       struct dirent *de;
-       int ret = 0;
-       struct readdir_callback_data d;
-
-       (void)offset;
-       (void)fi;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "readdir for '%s'\n",
-               path);
-       de = gn_dirent_find(path);
-       if(de == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "readdir: file not found\n");
-               return -ENOENT;
-       }
-       if(de->de_type != DE_DIR)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "readdir: not a directory\n");
-               gn_dirent_put(de);
-               ret = -ENOENT;
-               goto out;
-       }
-       filler(buf, ".", NULL, 0);
-       filler(buf, "..", NULL, 0);
-       if(uri_files)
-       {
-               filler(buf, URI_FILE, NULL, 0);
-               d.filler = filler;
-               d.buf = buf;
-               d.prefix = ".uri.";
-               ret = gn_directory_foreach(de, readdir_callback, &d);
-               if(ret == -1)
-               {
-                       ret = -ENOENT;
-                       goto out;
-               }
-       }
-       d.filler = filler;
-       d.buf = buf;
-       d.prefix = NULL;
-       ret = gn_directory_foreach(de, readdir_callback, &d);
-       if(ret == -1)
-               ret = -ENOENT;
-out:
-       gn_dirent_put(de);
-       return ret;
-}

Deleted: gnunet-fuse/release.c
===================================================================
--- gnunet-fuse/release.c       2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/release.c       2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,63 +0,0 @@
-/*
- * 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 <fuse.h>
-#include "gnfs.h"
-
-int gn_release(const char *path, struct fuse_file_info *fi)
-{
-       struct dirent *de;
-       int dirty = GN_UNLOCK_CLEAN;
-
-       (void)fi;
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_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;
-
-       /* Un-dirty ourselfs */
-       if(gn_file_upload_locked(de) == 0)
-       {
-               /* Now we must mark every containing directory dirty */
-               dirty = GN_UNLOCK_ANCESTORS_DIRTY;
-       }
-
-       gn_unlock_path(de, dirty);
-       gn_dirent_put(de);
-       return 0;
-}

Deleted: gnunet-fuse/rename.c
===================================================================
--- gnunet-fuse/rename.c        2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/rename.c        2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,135 +0,0 @@
-/*
- * rename.c - FUSE rename 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-static gboolean rename_callback(struct dirent *de, void *data)
-{
-       int *empty = data;
-
-       (void)de;
-       *empty = 0;
-       return 1;
-}
-
-int gn_rename(const char *from, const char *to)
-{
-       struct dirent *from_de, *to_de, *from_parent_de, *to_parent_de;
-       char *from_parent, *from_file, *to_parent, *to_file;
-       int ret = 0, empty = 1;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: '%s' to '%s'\n",
-               __FUNCTION__, from, to);
-
-       /* Check for special file */
-       if(gn_exists_special_file(from) || gn_exists_special_file(to))
-               return -EACCES;
-
-       /* Make sure 'from' exists */
-       from_de = gn_dirent_find(from);
-       if(from_de == NULL)
-               return -ENOENT;
-
-       /* We need to check some things before we remove 'from' */
-       to_de = gn_dirent_find(to);
-       if(to_de != NULL)
-       {
-               if(from_de->de_type == DE_FILE && to_de->de_type == DE_DIR)
-               {
-                       ret = -EISDIR;
-                       goto out;
-               }
-               if(from_de->de_type == DE_DIR && to_de->de_type == DE_FILE)
-               {
-                       ret = -ENOTDIR;
-                       goto out;
-               }
-               if(to_de->de_type == DE_DIR)
-               {
-                       gn_directory_foreach(to_de, rename_callback, &empty);
-                       if(!empty)
-                       {
-                               ret = -ENOTEMPTY;
-                               goto out;
-                       }
-               }
-       }
-
-       /* Now we can remove the 'from' */
-       from_parent = gn_dirname(from, &from_file);
-       from_parent_de = gn_dirent_find(from_parent);
-       GNUNET_free(from_parent);
-       if(from_parent_de == NULL)
-       {
-               ret = -ENOENT;
-               goto out;
-       }
-       gn_directory_remove(from_parent_de, from_de);
-       gn_dirent_put(from_parent_de);
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: removed '%s'\n",
-               __FUNCTION__, from);
-
-       /* Modify our path */
-       gn_dirent_path_set(from_de, to);
-
-       /* Replace the 'to' */
-       to_parent = gn_dirname(to, &to_file);
-       to_parent_de = gn_dirent_find(to_parent);
-       GNUNET_free(to_parent);
-       if(to_parent_de == NULL)
-       {
-               ret = -EIO;
-               goto out;
-       }
-
-       /* We should have some kind of directory_remove_insert for atomicity */
-       if(to_de != NULL)
-       {
-               if(gn_directory_remove(to_parent_de, to_de) == -1)
-               {
-                       gn_dirent_put(to_parent_de);
-                       ret = -EIO;
-                       goto out;
-               }
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: removed '%s'\n", __FUNCTION__, to);
-       }
-       if(gn_directory_insert(to_parent_de, from_de) == -1)
-       {
-               gn_dirent_put(to_parent_de);
-               ret = -EIO;
-               goto out;
-       }
-       gn_dirent_put(to_parent_de);
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: inserted '%s'\n", __FUNCTION__, to);
-
-out:
-       if(to_de != NULL)
-               gn_dirent_put(to_de);
-       if(from_de != NULL)
-               gn_dirent_put(from_de);
-       return ret;
-}

Deleted: gnunet-fuse/rmdir.c
===================================================================
--- gnunet-fuse/rmdir.c 2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/rmdir.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,78 +0,0 @@
-/*
- * rmdir.c - FUSE rmdir 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-static gboolean rmdir_callback(struct dirent *de, void *data)
-{
-       int *empty = data;
-
-       (void)de;
-       *empty = 0;
-       return 1;
-}
-
-int gn_rmdir(const char *path)
-{
-       struct dirent *de, *dechild;
-       char *parent, *file;
-       int ret, empty = 1;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -ENOTDIR;
-
-       /* Check for existing file */
-       dechild = gn_dirent_find(path);
-       if(dechild == NULL)
-               return -ENOENT;
-
-       /* Can't rmdir a non-empty directory */
-       gn_directory_foreach(dechild, rmdir_callback, &empty);
-       if(!empty)
-       {
-               gn_dirent_put(dechild);
-               return -ENOTEMPTY;
-       }
-
-       /* Remove directory */
-       parent = gn_dirname(path, &file);
-       de = gn_dirent_find(parent);
-       GNUNET_free(parent);
-       if(de == NULL)
-       {
-               gn_dirent_put(dechild);
-               return -ENOENT;
-       }
-       ret = gn_directory_remove(de, dechild);
-       gn_dirent_put(dechild);
-       gn_dirent_put(de);
-       if(ret == -1)
-               return -EIO;
-       return 0;
-}

Deleted: gnunet-fuse/special_file.c
===================================================================
--- gnunet-fuse/special_file.c  2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/special_file.c  2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,159 +0,0 @@
-/*
- * special_file.c - special file support (like .uri)
- *
- * 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 <string.h>
-#include <GNUnet/gnunet_util_string.h>
-#include <GNUnet/gnunet_ecrs_lib.h>
-#include "gnfs.h"
-
-char *gn_dirname(const char *path, char **file)
-{
-       char *parent, *slash;
-
-       parent = GNUNET_strdup(path);
-       slash = strrchr(parent, G_DIR_SEPARATOR);
-       if(slash != NULL)
-       {
-               slash[0] = '\0';
-               slash++;
-       }
-       if(file != NULL)
-               *file = slash;
-       return parent;
-}
-
-/* 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;
-
-       parent = gn_dirname(path, &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 = GNUNET_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);
-               GNUNET_free(actual_file);
-               if(de == NULL)
-                       goto out;
-               gn_dirent_put(de);
-               ret = 1;
-       }
-out:
-       GNUNET_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;
-       char *buf = NULL, *file, *parent;
-
-       parent = gn_dirname(path, &file);
-
-       /* Check for special file name */
-       if(strcmp(file, URI_FILE) == 0)
-       {
-               /* Return URI of the 'current' directory */
-               de = gn_dirent_find(parent);
-               if(de == NULL)
-                       goto out;
-               if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == 
GNUNET_SYSERR)
-               {
-                       gn_dirent_put(de);
-                       goto out;
-               }
-               if(de->de_dirty)
-               {
-                       if(gn_directory_upload_locked(de) == -1)
-                       {
-                               GNUNET_semaphore_up(de->de_sema);
-                               gn_dirent_put(de);
-                               goto out;
-                       }
-               }
-               buf = GNUNET_ECRS_uri_to_string(de->de_fi.uri);
-               GNUNET_semaphore_up(de->de_sema);
-               gn_dirent_put(de);
-               buf = GNUNET_realloc(buf, strlen(buf) + 2);
-               strcat(buf, "\n");
-       }
-       else if(strncmp(file, URI_FILE ".", URI_LEN + 1) == 0)
-       {
-               char *actual_file = GNUNET_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);
-               GNUNET_free(actual_file);
-               if(de == NULL)
-                       goto out;
-               if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == 
GNUNET_SYSERR)
-               {
-                       gn_dirent_put(de);
-                       goto out;
-               }
-               if(de->de_dirty)
-               {
-                       if(de->de_type == DE_DIR)
-                       {
-                               if(gn_directory_upload_locked(de) == -1)
-                               {
-                                       GNUNET_semaphore_up(de->de_sema);
-                                       gn_dirent_put(de);
-                                       goto out;
-                               }
-                       }
-                       else
-                       {
-                               if(de->de_fi.uri == NULL)
-                               {
-                                       GNUNET_semaphore_up(de->de_sema);
-                                       gn_dirent_put(de);
-                                       goto out;
-                               }
-                       }
-               }
-               buf = GNUNET_ECRS_uri_to_string(de->de_fi.uri);
-               GNUNET_semaphore_up(de->de_sema);
-               gn_dirent_put(de);
-               buf = GNUNET_realloc(buf, strlen(buf) + 2);
-               strcat(buf, "\n");
-       }
-out:
-       GNUNET_free(parent);
-       return buf;
-}

Deleted: gnunet-fuse/truncate.c
===================================================================
--- gnunet-fuse/truncate.c      2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/truncate.c      2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,90 +0,0 @@
-/*
- * truncate.c - FUSE truncate 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 <errno.h>
-#include <unistd.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_truncate(const char *path, off_t size)
-{
-       struct dirent *de;
-       int ret = 0, dirty = GN_UNLOCK_CLEAN;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: called for '%s' %lld bytes\n", __FUNCTION__, path, size);
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -EACCES;
-
-       /* Lookup dirent for path */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: file not found\n", __FUNCTION__);
-               return -ENOENT;
-       }
-       if(de->de_type != DE_FILE)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: not a file\n", __FUNCTION__);
-               ret = -EISDIR;
-               goto out;
-       }
-
-       /* Lock our path */
-       if(gn_lock_path(de) == -1)
-       {
-               ret = -EIO;
-               goto out;
-       }
-       if(!de->de_cached)
-       {
-               if(gn_file_download_locked(de) == -1)
-               {
-                       ret = -EIO;
-                       goto out_unlock;
-               }
-       }
-
-       /* Perform truncate */
-       ret = ftruncate(de->de_fd, size);
-       if(ret == -1)
-       {
-               ret = -errno;
-               goto out_unlock;
-       }
-
-       /* Mark us dirty */
-       de->de_dirty = 1;
-
-       /* Then un-mark us dirty */
-       if(gn_file_upload_locked(de) == 0)
-       {
-               dirty = GN_UNLOCK_ANCESTORS_DIRTY;
-       }
-out_unlock:
-       gn_unlock_path(de, GN_UNLOCK_ANCESTORS_DIRTY);
-out:
-       gn_dirent_put(de);
-       return ret;
-}

Deleted: gnunet-fuse/unlink.c
===================================================================
--- gnunet-fuse/unlink.c        2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/unlink.c        2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,68 +0,0 @@
-/*
- * unlink.c - FUSE unlink 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 <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_unlink(const char *path)
-{
-       struct dirent *de, *dechild;
-       char *parent, *file;
-       int ret;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -EPERM;
-
-       /* Check for existing file */
-       dechild = gn_dirent_find(path);
-       if(dechild == NULL)
-               return -ENOENT;
-       
-       /* Can't unlink a directory */
-       if(dechild->de_type != DE_FILE)
-       {
-               gn_dirent_put(dechild);
-               return -EPERM;
-       }
-
-       /* Remove file from parent dir */
-       parent = gn_dirname(path, &file);
-       de = gn_dirent_find(parent);
-       GNUNET_free(parent);
-       if(de == NULL)
-       {
-               gn_dirent_put(dechild);
-               return -ENOENT;
-       }
-       ret = gn_directory_remove(de, dechild);
-       gn_dirent_put(dechild);
-       gn_dirent_put(de);
-       if(ret == -1)
-               return -EIO;
-       return 0;
-}

Deleted: gnunet-fuse/utimens.c
===================================================================
--- gnunet-fuse/utimens.c       2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/utimens.c       2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,72 +0,0 @@
-/*
- * utimens.c - FUSE utimens 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
- */
-
-#define _GNU_SOURCE
-#include <sys/time.h>
-#include <string.h>
-#include <errno.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_utimens(const char *path, const struct timespec ts[2])
-{
-       struct dirent *de;
-       struct timeval tv[2];
-       int ret = 0;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, path);
-
-       /* Check to see if this is a special file */
-       if(gn_exists_special_file(path))
-               return -EACCES;
-
-       /* Get file or dir */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-               return -ENOENT;
-
-       /* If it's a cached file just call utime */
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-       {
-               gn_dirent_put(de);
-               return -EIO;
-       }
-       if(de->de_cached && de->de_type == DE_FILE)
-       {
-               TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
-               TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
-               ret = utimes(path, tv);
-               if(ret == -1)
-               {
-                       ret = -errno;
-                       GNUNET_GE_LOG_STRERROR(ectx, GNUNET_GE_BULK | 
GNUNET_GE_USER | GNUNET_GE_ERROR,
-                               "utimes");
-                       goto out;
-               }
-               goto out;
-       }
-
-       /* For now we do nothing otherwise */
-out:
-       GNUNET_semaphore_up(de->de_sema);
-       gn_dirent_put(de);
-       return ret;
-}

Deleted: gnunet-fuse/write.c
===================================================================
--- gnunet-fuse/write.c 2012-03-08 23:45:33 UTC (rev 20388)
+++ gnunet-fuse/write.c 2012-03-09 08:38:54 UTC (rev 20389)
@@ -1,88 +0,0 @@
-/*
- * write.c - FUSE write 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
- */
-
-#define _XOPEN_SOURCE 500
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fuse.h>
-#include "gnfs.h"
-
-int gn_write(const char *path, const char *buf, size_t size, off_t offset,
-       struct fuse_file_info *fi)
-{
-       struct dirent *de;
-       ssize_t slen;
-
-       (void)fi;
-
-       GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-               "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
-
-       /* Check for special file */
-       if(gn_exists_special_file(path))
-               return -EACCES;
-
-       /* Lookup dirent for path */
-       de = gn_dirent_find(path);
-       if(de == NULL)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: file not found\n", __FUNCTION__);
-               return -ENOENT;
-       }
-       if(de->de_type != DE_FILE)
-       {
-               GNUNET_GE_LOG(ectx, GNUNET_GE_BULK | GNUNET_GE_DEVELOPER | 
GNUNET_GE_DEBUG,
-                       "%s: not a file\n", __FUNCTION__);
-               size = -ENOENT;
-               goto out;
-       }
-
-       /* We must be cached */
-       if(GNUNET_semaphore_down(de->de_sema, GNUNET_YES) == GNUNET_SYSERR)
-       {
-               size = -EIO;
-               goto out;
-       }
-       if(!de->de_cached)
-       {
-               if(gn_file_download_locked(de) == -1)
-               {
-                       size = -EIO;
-                       goto out_unlock;
-               }
-       }
-
-       /* Perform write on temp file */
-       slen = pwrite(de->de_fd, buf, size, offset);
-       if(slen == -1)
-               size = -errno;
-       else
-               size = slen;
-
-       /* Mark us dirty */
-       de->de_dirty = 1;
-out_unlock:
-       GNUNET_semaphore_up(de->de_sema);
-out:
-       gn_dirent_put(de);
-       return size;
-}




reply via email to

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