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