[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r5153 - gnunet-fuse
From: |
gnunet |
Subject: |
[GNUnet-SVN] r5153 - gnunet-fuse |
Date: |
Wed, 27 Jun 2007 23:10:02 -0600 (MDT) |
Author: amatus
Date: 2007-06-27 23:10:01 -0600 (Wed, 27 Jun 2007)
New Revision: 5153
Added:
gnunet-fuse/mknod.c
gnunet-fuse/write.c
Modified:
gnunet-fuse/Makefile.am
gnunet-fuse/dirent.c
gnunet-fuse/getattr.c
gnunet-fuse/gnfs.h
gnunet-fuse/main.c
gnunet-fuse/open.c
gnunet-fuse/read.c
gnunet-fuse/special_file.c
Log:
First steps towards write support. You can now create files and write to them,
but they are not published.
Modified: gnunet-fuse/Makefile.am
===================================================================
--- gnunet-fuse/Makefile.am 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/Makefile.am 2007-06-28 05:10:01 UTC (rev 5153)
@@ -4,10 +4,12 @@
dirent.c \
getattr.c \
main.c \
+ mknod.c \
open.c \
read.c \
readdir.c \
special_file.c \
+ write.c \
gnfs.h \
gettext.h
Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/dirent.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <glib.h>
#include <string.h>
+#include <errno.h>
#include "gnfs.h"
GHashTable *path_hash;
@@ -119,7 +120,7 @@
de->de_dirty = 1;
if(type == DE_FILE)
{
- char filename[] = "/tmp/gnfsXXXXXX";
+ char filename[] = GN_MKSTEMP_FILE;
de->de_fd = mkstemp(filename);
de->de_filename = STRDUP(filename);
@@ -264,9 +265,7 @@
ECRS_FileInfo *fis;
};
-int dirent_upload_locked(struct dirent *de);
-
-void upload_foreach(gpointer key, gpointer value, gpointer data)
+static void upload_foreach(gpointer key, gpointer value, gpointer data)
{
struct dirent *de = value;
struct upload_data *d = data;
@@ -284,18 +283,17 @@
}
else
{
- dirent_upload_locked(de);
+ gn_dirent_upload_locked(de);
}
}
+ d->fis[d->count].uri = ECRS_dupUri(de->de_fi.uri);
+ d->fis[d->count].meta = ECRS_dupMetaData(de->de_fi.meta);
d->count++;
- d->fis = REALLOC(d->fis, d->count * sizeof(*d->fis));
- d->fis[d->count - 1].uri = ECRS_dupUri(de->de_fi.uri);
- d->fis[d->count - 1].meta = ECRS_dupMetaData(de->de_fi.meta);
out:
SEMAPHORE_UP(de->de_file_sema);
}
-void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
+static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
void *closure)
{
(void)totalBytes;
@@ -304,65 +302,126 @@
(void)closure;
}
-int tt(void *closure)
+static int tt(void *closure)
{
(void)closure;
return fuse_interrupted() ? SYSERR : OK;
}
-int dirent_upload_locked(struct dirent *de)
+/*
+ * Make a dirty dirent clean - it should be a good tradeoff to only upload
+ * changes to directories here and upload changes to files on release
+ */
+int gn_dirent_upload_locked(struct dirent *de)
{
- int i, fd;
+ int i, ret, fd;
struct upload_data d;
- char *buf, filename[] = "/tmp/gnfsXXXXXX";
+ char *buf, filename[] = GN_MKSTEMP_FILE;
guint64 len;
struct ECRS_URI *uri;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: called for '%s'\n", __FUNCTION__, de->de_path);
+
+ /* We may be already clean */
if(!de->de_dirty)
return 0;
+
+ /* Collect FileInfo from hash table and make a GNUnet directory*/
d.count = 0;
- d.fis = NULL;
+ d.fis = MALLOC(g_hash_table_size(de->de_dir) * sizeof(*d.fis));
g_hash_table_foreach(de->de_dir, upload_foreach, &d);
- if(ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
- de->de_fi.meta) == SYSERR)
- goto out;
+ ret = ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
+ de->de_fi.meta);
+ for(i = 0; i < d.count; i++)
+ {
+ ECRS_freeUri(d.fis[i].uri);
+ ECRS_freeMetaData(d.fis[i].meta);
+ }
+ if(ret == SYSERR)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: ECRS_createDirectory failed\n",
+ __FUNCTION__);
+ return -1;
+ }
+ FREE(d.fis);
+
+ /* Write the GNUnet directory out to a file and upload it */
fd = mkstemp(filename);
if(fd == -1)
- goto out;
+ {
+ GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
+ | GE_ERROR, "mkstemp", filename);
+ return -1;
+ }
write(fd, buf, len);
+ ret = ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
+ -1, upcb, NULL, tt, NULL, &uri);
close(fd);
- if(ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
- -1, upcb, NULL, tt, NULL, &uri) == SYSERR)
- goto out_unlink_file;
+ unlink(filename);
+ if(ret == SYSERR)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+ "%s: ECRS_uploadFile failed\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Update the dirent info with our new URI and mark it clean */
if(de->de_fi.uri != NULL)
ECRS_freeUri(de->de_fi.uri);
de->de_fi.uri = uri;
g_hash_table_destroy(de->de_dir);
de->de_dirty = 0;
-out_unlink_file:
- unlink(filename);
-out:
- for(i = 0; i < d.count; i++)
- {
- ECRS_freeUri(d.fis[i].uri);
- ECRS_freeMetaData(d.fis[i].meta);
- }
- FREE(d.fis);
return 0;
}
+static void dpcb(unsigned long long totalBytes,
+ unsigned long long completedBytes, cron_t 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;
+}
+
/*
- * Make a dirty dirent clean - it should be a good tradeoff to only upload
- * changes to directories here and upload changes to files on release
+ * Download a file for writing, de_file_sema must be held.
*/
-int gn_dirent_upload(struct dirent *de)
+int gn_dirent_download_locked(struct dirent *de)
{
- int ret;
+ char filename[] = GN_MKSTEMP_FILE;
- if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ /* We may already be dirty */
+ if(!de->de_dirty)
+ return 0;
+
+ /* Do the download */
+ de->de_fd = mkstemp(filename);
+ if(de->de_fd == -1)
+ {
+ GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
+ | GE_ERROR, "mkstemp", filename);
return -1;
- ret = dirent_upload_locked(de);
- SEMAPHORE_UP(de->de_file_sema);
- return ret;
+ }
+ de->de_filename = STRDUP(filename);
+
+ if(ECRS_downloadFile(ectx, cfg, de->de_fi.uri, filename, anonymity,
+ dpcb, NULL, tt, NULL) == SYSERR)
+ {
+ close(de->de_fd);
+ FREE(de->de_filename);
+ return -1;
+ }
+
+ /* Mark ourselves dirty, we don't have to mark our parent directory
+ * dirty until we sync this file back into GNUnet, see above. */
+ de->de_dirty = 1;
+ return 0;
}
Modified: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/getattr.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -19,7 +19,6 @@
*/
#include <sys/stat.h>
-#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fuse.h>
@@ -30,8 +29,8 @@
struct dirent *de;
guint64 size = 0;
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "getattr for '%s'\n",
- path);
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+ __FUNCTION__, path);
/* Check to see if this is a special file */
if(gn_exists_special_file(path))
@@ -47,7 +46,7 @@
de = gn_dirent_find(path);
if(de == NULL)
{
- GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
+ GE_LOG(ectx, GE_BULK | GE_USER | GE_DEBUG,
"%s: could not find path '%s'\n", __FUNCTION__, path);
return -ENOENT;
}
@@ -57,7 +56,7 @@
stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
stbuf->st_nlink = 1;
if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
- return -ENOENT;
+ return -EIO;
if(de->de_dirty)
{
if(de->de_type == DE_FILE && disk_file_size(ectx,
@@ -68,7 +67,7 @@
__FUNCTION__, de->de_filename);
SEMAPHORE_UP(de->de_file_sema);
gn_dirent_put(de);
- return -ENOENT;
+ return -EIO;
}
}
else
Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/gnfs.h 2007-06-28 05:10:01 UTC (rev 5153)
@@ -34,6 +34,7 @@
#define URI_FILE ".uri"
#define URI_LEN 4
+#define GN_MKSTEMP_FILE "/tmp/gnfs.XXXXXX"
struct dirent
{
@@ -81,6 +82,8 @@
void gn_dirent_cache_init(void);
void gn_dirent_cache(struct dirent *de);
struct dirent *gn_dirent_find(const gchar *path);
+int gn_dirent_upload_locked(struct dirent *de);
+int gn_dirent_download_locked(struct dirent *de);
/* directory.c */
int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
@@ -91,11 +94,15 @@
int gn_getattr(const char *path, struct stat *stbuf);
int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi);
+int gn_mknod(const char *path, mode_t mode, dev_t rdev);
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,
+ struct fuse_file_info *fi);
/* special_file.c */
+char *gn_dirname(const char *path, char **file);
int gn_exists_special_file(const char *path);
char *gn_get_special_file(const char *path);
Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/main.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <glib.h>
#include <fuse.h>
#include <GNUnet/gnunet_directories.h>
@@ -59,7 +60,6 @@
(void)scls;
(void)cmdLineOption;
- fuse_argv = REALLOC(fuse_argv, sizeof(char *) * (fuse_argc + 2));
fuse_argv[fuse_argc] = (char *)value;
fuse_argc++;
fuse_argv[fuse_argc] = NULL;
@@ -70,8 +70,10 @@
{
.getattr = gn_getattr,
.readdir = gn_readdir,
+ .mknod = gn_mknod,
.open = gn_open,
.read = gn_read,
+ .write = gn_write,
};
static struct CommandLineOption gn_options[] =
@@ -102,7 +104,7 @@
/* Initialize fuse options */
fuse_argc = 1;
- fuse_argv = MALLOC(sizeof(char *) * (fuse_argc + 1));
+ fuse_argv = MALLOC(sizeof(char *) * argc);
fuse_argv[0] = argv[0];
fuse_argv[1] = NULL;
Added: gnunet-fuse/mknod.c
===================================================================
--- gnunet-fuse/mknod.c (rev 0)
+++ gnunet-fuse/mknod.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -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 ECRS_MetaData *meta;
+ char *parent, *file;
+
+ (void)rdev;
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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)
+ {
+ FREE(parent);
+ return -ENOENT;
+ }
+ meta = ECRS_createMetaData();
+ ECRS_addToMetaData(meta, EXTRACTOR_FILENAME, file);
+ newde = gn_dirent_new(path, NULL, meta, DE_FILE);
+ ECRS_freeMetaData(meta);
+ if(gn_directory_insert(de, newde) == -1)
+ {
+ gn_dirent_put(de);
+ gn_dirent_put(newde);
+ FREE(parent);
+ return -EIO;
+ }
+ gn_dirent_put(de);
+ gn_dirent_put(newde);
+ FREE(parent);
+ return 0;
+}
Modified: gnunet-fuse/open.c
===================================================================
--- gnunet-fuse/open.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/open.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -18,31 +18,34 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <stdio.h>
-#include <fuse.h>
#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;
- (void)fi;
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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)
- {
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "%s: file not found\n", __FUNCTION__);
return -ENOENT;
- }
if(de->de_type != DE_FILE)
{
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
@@ -51,5 +54,7 @@
return -ENOENT;
}
gn_dirent_put(de);
+ if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ return -EEXIST;
return 0;
}
Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/read.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -82,8 +82,8 @@
(void)fi;
- GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "read '%s' %d bytes\n",
- path, size);
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
/* Check for special file */
special = gn_get_special_file(path);
@@ -109,19 +109,19 @@
if(de == NULL)
{
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "read: file not found\n");
+ "%s: file not found\n", __FUNCTION__);
return -ENOENT;
}
if(de->de_type != DE_FILE)
{
GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
- "read: not a file\n");
+ "%s: not a file\n", __FUNCTION__);
size = -ENOENT;
goto out;
}
if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
{
- size = -EINTR;
+ size = -EIO;
goto out;
}
if(de->de_dirty)
@@ -151,7 +151,7 @@
if(ret != OK)
{
GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
- "%s: failed to download directory\n", __FUNCTION__);
+ "%s: failed to download file\n", __FUNCTION__);
size = -ENODATA;
}
out_sema_up:
Modified: gnunet-fuse/special_file.c
===================================================================
--- gnunet-fuse/special_file.c 2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/special_file.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -23,6 +23,22 @@
#include <GNUnet/gnunet_ecrs_lib.h>
#include "gnfs.h"
+char *gn_dirname(const char *path, char **file)
+{
+ char *parent, *slash;
+
+ parent = 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)
{
@@ -30,13 +46,7 @@
char *file, *parent;
int ret = 0;
- /* Break path into parent and file (dirname and basename kinda) */
- parent = STRDUP(path);
- file = strrchr(parent, G_DIR_SEPARATOR);
- if(file == NULL)
- goto out;
- file[0] = '\0';
- file++;
+ parent = gn_dirname(path, &file);
/* Check for special file name */
if(strcmp(file, URI_FILE) == 0)
@@ -71,13 +81,7 @@
struct dirent *de;
char *buf = NULL, *file, *parent;
- /* Break path into parent and file (dirname and basename kinda) */
- parent = STRDUP(path);
- file = strrchr(parent, G_DIR_SEPARATOR);
- if(file == NULL)
- goto out;
- file[0] = '\0';
- file++;
+ parent = gn_dirname(path, &file);
/* Check for special file name */
if(strcmp(file, URI_FILE) == 0)
Added: gnunet-fuse/write.c
===================================================================
--- gnunet-fuse/write.c (rev 0)
+++ gnunet-fuse/write.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -0,0 +1,85 @@
+/*
+ * 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, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ struct dirent *de;
+ ssize_t slen;
+
+ (void)fi;
+
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | 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)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: file not found\n", __FUNCTION__);
+ return -ENOENT;
+ }
+ if(de->de_type != DE_FILE)
+ {
+ GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+ "%s: not a file\n", __FUNCTION__);
+ size = -ENOENT;
+ goto out;
+ }
+
+ /* We must be dirty */
+ if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+ {
+ size = -EIO;
+ goto out;
+ }
+ if(!de->de_dirty)
+ {
+ if(gn_dirent_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;
+out_unlock:
+ SEMAPHORE_UP(de->de_file_sema);
+out:
+ gn_dirent_put(de);
+ return size;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r5153 - gnunet-fuse,
gnunet <=