gnunet-fuse

GNUnet file-sharing directory mounting via FUSE
Log | Files | Refs | Submodules | README | LICENSE

commit 4607ff02f5ec32b021ebd6610383dd79fca74189
parent 90989f282e9fa2d866783daa04730d235b8e6aea
Author: David Barksdale <amatus.amongus@gmail.com>
Date:   Thu, 26 Jul 2007 05:48:35 +0000

Finished support for truncate

Diffstat:
MChangeLog | 2++
MMakefile.am | 1+
Mdirent.c | 59-----------------------------------------------------------
Afile.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgnfs.h | 11+++++++----
Mmain.c | 4++--
Mrelease.c | 47+++++------------------------------------------
Mtruncate.c | 16+++++++++++-----
Mwrite.c | 2+-
9 files changed, 154 insertions(+), 113 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,5 @@ +2007-07-26 David Barksdale <amatus@gnu.org> 0.7.2-5 +* Finished support for truncate 2007-07-17 David Barksdale <amatus@gnu.org> 0.7.2-4 * Added support for renaming files 2007-07-12 David Barksdale <amatus@gnu.org> 0.7.2-3 diff --git a/Makefile.am b/Makefile.am @@ -2,6 +2,7 @@ bin_PROGRAMS = gnunet-fs gnunet_fs_SOURCES = \ directory.c \ dirent.c \ + file.c \ getattr.c \ main.c \ mkdir.c \ diff --git a/dirent.c b/dirent.c @@ -383,62 +383,3 @@ int gn_unlock_path(struct dirent *de, int dirty) FREE(path); 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; -} - -static int tt(void *closure) -{ - (void)closure; - return fuse_interrupted() ? SYSERR : OK; -} - -/* - * Download a file for writing, de_sema must be held. - */ -int gn_dirent_download_locked(struct dirent *de) -{ - char filename[] = GN_MKSTEMP_FILE; - - /* We may already be cached */ - if(de->de_cached) - 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; - } - de->de_filename = STRDUP(filename); - - GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, - "%s: downloading '%s'\n", __FUNCTION__, de->de_filename); - if(ECRS_downloadFile(ectx, cfg, de->de_fi.uri, filename, anonymity, - dpcb, NULL, tt, NULL) == SYSERR) - { - GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR, - "%s: download failed\n", __FUNCTION__); - close(de->de_fd); - unlink(de->de_filename); - FREE(de->de_filename); - return -1; - } - - /* Mark ourselves cached */ - de->de_cached = 1; - return 0; -} diff --git a/file.c b/file.c @@ -0,0 +1,125 @@ +/* + * 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 OK; + if(fuse_interrupted()) + return SYSERR; + return OK; +} + +static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta, + void *closure) +{ + (void)totalBytes; + (void)completedBytes; + (void)eta; + (void)closure; +} + +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; +} + +/* + * 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) + { + GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER + | GE_ERROR, "mkstemp", filename); + return -1; + } + de->de_filename = STRDUP(filename); + + GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, + "%s: downloading '%s'\n", __FUNCTION__, de->de_filename); + if(ECRS_downloadFile(ectx, cfg, de->de_fi.uri, filename, anonymity, + dpcb, NULL, tt, NULL) == SYSERR) + { + GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR, + "%s: download failed\n", __FUNCTION__); + close(de->de_fd); + unlink(de->de_filename); + FREE(de->de_filename); + return -1; + } + + /* Mark ourselves cached */ + de->de_cached = 1; + return 0; +} + +int gn_file_upload_locked(struct dirent *de) +{ + struct ECRS_URI *uri; + + /* If we're not dirty then we're done */ + if(!de->de_dirty) + return 0; + + if(ECRS_uploadFile(ectx, cfg, de->de_filename, NO, anonymity, priority, + -1, upcb, NULL, tt, NULL, &uri) == SYSERR) + { + GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR, + "%s: upload failed\n", __FUNCTION__); + return -1; + } + if(de->de_fi.uri != NULL) + ECRS_freeUri(de->de_fi.uri); + de->de_fi.uri = uri; + de->de_cached = 0; + de->de_dirty = 0; + close(de->de_fd); + unlink(de->de_filename); + FREE(de->de_filename); + return 0; +} diff --git a/gnfs.h b/gnfs.h @@ -100,7 +100,6 @@ int gn_unlock_path(struct dirent *de, int dirty); #define GN_UNLOCK_CLEAN 0 #define GN_UNLOCK_ALL_DIRTY 1 #define GN_UNLOCK_ANCESTORS_DIRTY 2 -int gn_dirent_download_locked(struct dirent *de); /* directory.c */ int gn_directory_foreach(struct dirent *de, gn_dir_foreach_callback cb, @@ -110,23 +109,27 @@ int gn_directory_insert(struct dirent *de, struct dirent *dechild); int gn_directory_remove(struct dirent *de, struct dirent *dechild); int gn_directory_upload_locked(struct dirent *de); +/* file.c */ +int gn_file_download_locked(struct dirent *de); +int gn_file_upload_locked(struct dirent *de); + /* FUSE function files */ 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_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_truncate(const char *path, off_t size); -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, 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); +int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi); +int gn_utimens(const char *path, const struct timespec ts[2]); /* special_file.c */ char *gn_dirname(const char *path, char **file); diff --git a/main.c b/main.c @@ -72,18 +72,18 @@ int getopt_configure_argv(CommandLineProcessorContext *ctx, void *scls, static struct fuse_operations fops = { .getattr = gn_getattr, - .readdir = gn_readdir, .mknod = gn_mknod, .mkdir = gn_mkdir, .unlink = gn_unlink, .rmdir = gn_rmdir, .rename = gn_rename, .truncate = gn_truncate, - .utimens = gn_utimens, .open = gn_open, .read = gn_read, .write = gn_write, .release = gn_release, + .readdir = gn_readdir, + .utimens = gn_utimens, }; static struct CommandLineOption gn_options[] = diff --git a/release.c b/release.c @@ -18,31 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <unistd.h> #include <fuse.h> #include "gnfs.h" -static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta, - void *closure) -{ - (void)totalBytes; - (void)completedBytes; - (void)eta; - (void)closure; -} - -static int tt(void *closure) -{ - (void)closure; - - return fuse_interrupted() ? SYSERR : OK; -} - int gn_release(const char *path, struct fuse_file_info *fi) { struct dirent *de; - struct ECRS_URI *uri; - gboolean dirty = GN_UNLOCK_CLEAN; + int dirty = GN_UNLOCK_CLEAN; (void)fi; GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n", @@ -69,32 +51,13 @@ int gn_release(const char *path, struct fuse_file_info *fi) if(gn_lock_path(de) == -1) return 0; - /* If we're not dirty then we're done */ - if(!de->de_dirty) - goto out; - - /* Take this opportunity */ - GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, - "%s: uploading file\n", __FUNCTION__); - if(ECRS_uploadFile(ectx, cfg, de->de_filename, NO, anonymity, priority, - -1, upcb, NULL, tt, NULL, &uri) == SYSERR) + /* Un-dirty ourselfs */ + if(gn_file_upload_locked(de) == 0) { - GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR, - "%s: upload failed\n", __FUNCTION__); - goto out; + /* Now we must mark every containing directory dirty */ + dirty = GN_UNLOCK_ANCESTORS_DIRTY; } - if(de->de_fi.uri != NULL) - ECRS_freeUri(de->de_fi.uri); - de->de_fi.uri = uri; - de->de_cached = 0; - de->de_dirty = 0; - close(de->de_fd); - unlink(de->de_filename); - FREE(de->de_filename); - /* Now we must mark every containing directory dirty */ - dirty = GN_UNLOCK_ANCESTORS_DIRTY; -out: gn_unlock_path(de, dirty); gn_dirent_put(de); return 0; diff --git a/truncate.c b/truncate.c @@ -26,7 +26,7 @@ int gn_truncate(const char *path, off_t size) { struct dirent *de; - int ret = 0; + int ret = 0, dirty = GN_UNLOCK_CLEAN; GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: called for '%s' %lld bytes\n", __FUNCTION__, path, size); @@ -51,15 +51,15 @@ int gn_truncate(const char *path, off_t size) goto out; } - /* We must be cached */ - if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR) + /* Lock our path */ + if(gn_lock_path(de) == -1) { ret = -EIO; goto out; } if(!de->de_cached) { - if(gn_dirent_download_locked(de) == -1) + if(gn_file_download_locked(de) == -1) { ret = -EIO; goto out_unlock; @@ -76,8 +76,14 @@ int gn_truncate(const char *path, off_t size) /* 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: - SEMAPHORE_UP(de->de_sema); + gn_unlock_path(de, GN_UNLOCK_ANCESTORS_DIRTY); out: gn_dirent_put(de); return ret; diff --git a/write.c b/write.c @@ -64,7 +64,7 @@ int gn_write(const char *path, const char *buf, size_t size, off_t offset, } if(!de->de_cached) { - if(gn_dirent_download_locked(de) == -1) + if(gn_file_download_locked(de) == -1) { size = -EIO; goto out_unlock;