gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r5318 - gnunet-fuse


From: gnunet
Subject: [GNUnet-SVN] r5318 - gnunet-fuse
Date: Mon, 16 Jul 2007 23:31:53 -0600 (MDT)

Author: amatus
Date: 2007-07-16 23:31:52 -0600 (Mon, 16 Jul 2007)
New Revision: 5318

Added:
   gnunet-fuse/rename.c
Modified:
   gnunet-fuse/ChangeLog
   gnunet-fuse/Makefile.am
   gnunet-fuse/directory.c
   gnunet-fuse/dirent.c
   gnunet-fuse/gnfs.h
   gnunet-fuse/main.c
   gnunet-fuse/read.c
   gnunet-fuse/write.c
Log:
Added support for renaming files

Modified: gnunet-fuse/ChangeLog
===================================================================
--- gnunet-fuse/ChangeLog       2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/ChangeLog       2007-07-17 05:31:52 UTC (rev 5318)
@@ -1,3 +1,5 @@
+2007-07-17 David Barksdale <address@hidden> 0.7.2-4
+* Added support for renaming files
 2007-07-12 David Barksdale <address@hidden> 0.7.2-3
 * Added support for unlinking files, creating directories, and removing
 directories

Modified: gnunet-fuse/Makefile.am
===================================================================
--- gnunet-fuse/Makefile.am     2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/Makefile.am     2007-07-17 05:31:52 UTC (rev 5318)
@@ -10,6 +10,7 @@
        read.c \
        readdir.c \
        release.c \
+       rename.c \
        rmdir.c \
        special_file.c \
        unlink.c \

Modified: gnunet-fuse/directory.c
===================================================================
--- gnunet-fuse/directory.c     2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/directory.c     2007-07-17 05:31:52 UTC (rev 5318)
@@ -51,7 +51,7 @@
        int isRoot, void *data)
 {
        struct dirent *de, *deparent = data;
-       gchar *filename, *newpath, type;
+       gchar *filename, *path, *newpath, type;
        size_t len, rlen;
 
        (void)key;
@@ -78,11 +78,13 @@
                type = DE_FILE;
 
        /* Create newpath, the path to this entry */
-       rlen = strlen(deparent->de_path);
+       path = gn_dirent_path_get(deparent);
+       rlen = strlen(path);
        newpath = MALLOC(rlen + len + 1);
-       strcpy(newpath, deparent->de_path);
-       if(deparent->de_path[rlen - 1] != G_DIR_SEPARATOR)
+       strcpy(newpath, path);
+       if(path[rlen - 1] != G_DIR_SEPARATOR)
                strcat(newpath, G_DIR_SEPARATOR_S);
+       FREE(path);
        strcat(newpath, filename);
 
        /* Create a new dirent for this entry only if one doesn't already exist
@@ -100,9 +102,11 @@
        }
 
        /* Add it to the directory's list (steals our ref)*/
+       MUTEX_LOCK(de->de_path_mutex);
        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);
+       MUTEX_UNLOCK(de->de_path_mutex);
 
        /* Clean up */
        FREE(filename);
@@ -117,8 +121,6 @@
        int ret;
        guint64 len;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, de->de_path);
        len = ECRS_fileSize(de->de_fi.uri);
        mem = MALLOC(len);
        ret = ECRS_downloadPartialFile(ectx, cfg, de->de_fi.uri,
@@ -213,9 +215,6 @@
 
 int gn_directory_insert(struct dirent *de, struct dirent *dechild)
 {
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, dechild->de_path);
-
        /* Lock our path */
        if(gn_lock_path(de) == -1)
                return -1;
@@ -234,8 +233,10 @@
        }
 
        /* If we're already in there, bail out */
+       MUTEX_LOCK(dechild->de_path_mutex);
        if(g_hash_table_lookup(de->de_dir_hash, dechild->de_basename))
        {
+               MUTEX_UNLOCK(dechild->de_path_mutex);
                gn_unlock_path(de, GN_UNLOCK_CLEAN);
                return -1;
        }
@@ -243,6 +244,7 @@
        /* Insert the child in our de_dir_hash */
        gn_dirent_ref(dechild);
        g_hash_table_replace(de->de_dir_hash, dechild->de_basename, dechild);
+       MUTEX_UNLOCK(dechild->de_path_mutex);
 
        /* Cache the dirent */
        gn_dirent_cache_insert(dechild);
@@ -254,9 +256,6 @@
 
 int gn_directory_remove(struct dirent *de, struct dirent *dechild)
 {
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
-               __FUNCTION__, dechild->de_path);
-
        /* Lock our path */
        if(gn_lock_path(de) == -1)
                return -1;
@@ -274,13 +273,16 @@
        }
 
        /* Remove from dir_hash */
+       MUTEX_LOCK(dechild->de_path_mutex);
        if(!g_hash_table_remove(de->de_dir_hash, dechild->de_basename))
        {
+               MUTEX_UNLOCK(dechild->de_path_mutex);
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
                        "%s: not found in dir_hash\n",
                        __FUNCTION__);
                goto out_err;
        }
+       MUTEX_UNLOCK(dechild->de_path_mutex);
 
        /* Remove from dirent cache */
        gn_dirent_cache_remove(dechild);
@@ -359,9 +361,6 @@
        struct ECRS_URI *uri;
        struct dir_upload_data d;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: called for '%s'\n", __FUNCTION__, de->de_path);
-
        /* We may be already clean */
        if(!de->de_dirty)
                return 0;

Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c        2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/dirent.c        2007-07-17 05:31:52 UTC (rev 5318)
@@ -66,8 +66,9 @@
                return;
        }
        MUTEX_UNLOCK(de->de_refs_mutex);
+       MUTEX_DESTROY(de->de_path_mutex);
+       FREE(de->de_path);
        MUTEX_DESTROY(de->de_refs_mutex);
-       FREE(de->de_path);
        SEMAPHORE_DESTROY(de->de_sema);
        if(de->de_fi.uri != NULL)
                ECRS_freeUri(de->de_fi.uri);
@@ -92,6 +93,28 @@
        FREE(de);
 }
 
+char *gn_dirent_path_get(struct dirent *de)
+{
+       char *ret;
+
+       MUTEX_LOCK(de->de_path_mutex);
+       ret = STRDUP(de->de_path);
+       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)
+{
+       MUTEX_LOCK(de->de_path_mutex);
+       FREE(de->de_path);
+       de->de_path = STRDUP(path);
+       de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
+       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,
@@ -108,6 +131,7 @@
        struct dirent *de;
 
        de = MALLOC(sizeof(*de));
+       de->de_path_mutex = MUTEX_CREATE(0);
        de->de_path = STRDUP(path);
        de->de_basename = strrchr(de->de_path, G_DIR_SEPARATOR) + 1;
        de->de_refs_mutex = MUTEX_CREATE(0);
@@ -155,8 +179,10 @@
         * XXX: But what about diry entries?? */
        if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
                return;
+       MUTEX_LOCK(de->de_path_mutex);
        GE_ASSERT(ectx, !g_hash_table_lookup(path_hash, de->de_path));
        g_hash_table_replace(path_hash, de->de_path, de);
+       MUTEX_UNLOCK(de->de_path_mutex);
        gn_dirent_ref(de);
        SEMAPHORE_UP(path_sema);
 }
@@ -168,7 +194,10 @@
 {
        if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
                return;
+       /* This is safe because we still hold a ref */
+       MUTEX_LOCK(de->de_path_mutex);
        g_hash_table_remove(path_hash, de->de_path);
+       MUTEX_UNLOCK(de->de_path_mutex);
        SEMAPHORE_UP(path_sema);
 }
 
@@ -222,9 +251,6 @@
                /* If we found it then continue */
                if(next_de != NULL)
                {
-                       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                               "%s: found in cache '%s'\n", __FUNCTION__,
-                               next_de->de_path);
                        gn_dirent_put(de);
                        de = next_de;
                        continue;
@@ -240,9 +266,6 @@
                        de = NULL;
                        break;
                }
-               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "%s: found in directory '%s'\n", __FUNCTION__,
-                       next_de->de_path);
 
                /* Continue to the next path element */
                gn_dirent_put(de);
@@ -303,9 +326,12 @@
 int gn_lock_path(struct dirent *de)
 {
        struct dirent *detmp = NULL;
+       char *path;
 
-       if(gn_path_foreach(de->de_path, lock_path_callback, &detmp) == -1)
+       path = gn_dirent_path_get(de);
+       if(gn_path_foreach(path, lock_path_callback, &detmp) == -1)
        {
+               FREE(path);
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
                        "%s: failed!\n", __FUNCTION__);
                /* Back out all the locks we aquired */
@@ -313,6 +339,7 @@
                        gn_unlock_path(detmp, GN_UNLOCK_CLEAN);
                return -1;
        }
+       FREE(path);
        return 0;
 }
 
@@ -341,15 +368,19 @@
 int gn_unlock_path(struct dirent *de, int dirty)
 {
        struct unlock_path_data d;
+       char *path;
 
        d.dirty = dirty;
        d.de = de;
-       if(gn_path_foreach(de->de_path, unlock_path_callback, &d) == -1)
+       path = gn_dirent_path_get(de);
+       if(gn_path_foreach(path, unlock_path_callback, &d) == -1)
        {
+               FREE(path);
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
                        "%s: failed!\n", __FUNCTION__);
                return -1;
        }
+       FREE(path);
        return 0;
 }
 
@@ -380,8 +411,6 @@
 {
        char filename[] = GN_MKSTEMP_FILE;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: called for '%s'\n",
-               __FUNCTION__, de->de_path);
        /* We may already be cached */
        if(de->de_cached)
                return 0;

Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h  2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/gnfs.h  2007-07-17 05:31:52 UTC (rev 5318)
@@ -42,14 +42,17 @@
 
 struct dirent
 {
+       /* de_path_mutex protects de_path and de_basename */
+       struct MUTEX *de_path_mutex;
        gchar *de_path;
        gchar *de_basename;
+       /* de_refs_mutex protects de_refs */
        struct MUTEX *de_refs_mutex;
        gint de_refs;
        gchar de_type;
 #define DE_FILE        'f'
 #define DE_DIR 'd'
-       /* Access of anything below this must lock de_sema */
+       /* de_sema protects everything below */
        struct SEMAPHORE *de_sema;
        /* Cached entries have their entire contents in memory or on disk */
        gboolean de_cached;
@@ -86,6 +89,8 @@
 struct dirent *gn_dirent_get(const gchar *path);
 void gn_dirent_ref(struct dirent *de);
 void gn_dirent_put(struct dirent *de);
+char *gn_dirent_path_get(struct dirent *de);
+void gn_dirent_path_set(struct dirent *de, const char *path);
 void gn_dirent_cache_init(void);
 void gn_dirent_cache_insert(struct dirent *de);
 void gn_dirent_cache_remove(struct dirent *de);
@@ -113,11 +118,12 @@
 int gn_mkdir(const char *path, mode_t mode);
 int gn_unlink(const char *path);
 int gn_rmdir(const char *path);
+int gn_rename(const char *from, const char *to);
 int gn_utimens(const char *path, const struct timespec ts[2]);
 int gn_open(const char *path, struct fuse_file_info *fi);
 int gn_read(const char *path, char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi);
-int gn_write(const char *path, char *buf, size_t size, off_t offset,
+int gn_write(const char *path, const char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi);
 int gn_release(const char *path, struct fuse_file_info *fi);
 

Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c  2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/main.c  2007-07-17 05:31:52 UTC (rev 5318)
@@ -77,6 +77,7 @@
        .mkdir = gn_mkdir,
        .unlink = gn_unlink,
        .rmdir = gn_rmdir,
+       .rename = gn_rename,
        .utimens = gn_utimens,
        .open = gn_open,
        .read = gn_read,

Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c  2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/read.c  2007-07-17 05:31:52 UTC (rev 5318)
@@ -45,14 +45,10 @@
        (void)completedBytes;
        (void)eta;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: lastBlockOffset %llu lastBlockSize %d\n", __FUNCTION__,
-               lastBlockOffset, lastBlockSize);
-
        /* 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;
@@ -156,14 +152,8 @@
        d.buf = buf;
        d.size = size;
        d.offset = offset;
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: calling ECRS_downloadPartialFile %u bytes %lld offset\n",
-               __FUNCTION__, size, offset);
        ret = ECRS_downloadPartialFile(ectx, cfg, de->de_fi.uri, "/dev/null",
                offset, size, anonymity, YES, dpcb, &d, tt, NULL);
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: ECRS_downloadPartialFile returned %d\n",
-               __FUNCTION__, ret);
        if(ret != OK)
        {
                GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,

Added: gnunet-fuse/rename.c
===================================================================
--- gnunet-fuse/rename.c                                (rev 0)
+++ gnunet-fuse/rename.c        2007-07-17 05:31:52 UTC (rev 5318)
@@ -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;
+
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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);
+       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);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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);
+       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;
+               }
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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;
+}

Modified: gnunet-fuse/write.c
===================================================================
--- gnunet-fuse/write.c 2007-07-16 21:28:24 UTC (rev 5317)
+++ gnunet-fuse/write.c 2007-07-17 05:31:52 UTC (rev 5318)
@@ -25,7 +25,7 @@
 #include <fuse.h>
 #include "gnfs.h"
 
-int gn_write(const char *path, char *buf, size_t size, off_t offset,
+int gn_write(const char *path, const char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi)
 {
        struct dirent *de;





reply via email to

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