gnunet-fuse

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

commit 5e030dc68bb30ff75d0d0655a863d0394aa915c4
parent 861baeea4bc0f57f81eddac2724e96d59c03eff9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  3 Jun 2012 19:36:09 +0000

-towards reading dirs

Diffstat:
Msrc/fuse/gnunet-fuse.c | 36++++++++++++++++++++++++++----------
Msrc/fuse/gnunet-fuse.h | 2+-
Msrc/fuse/readdir.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
3 files changed, 169 insertions(+), 73 deletions(-)

diff --git a/src/fuse/gnunet-fuse.c b/src/fuse/gnunet-fuse.c @@ -2,10 +2,11 @@ This file is part of gnunet-fuse. (C) 2012 Christian Grothoff (and other contributing authors) - 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 free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + 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 @@ -57,10 +58,26 @@ struct GNUNET_FUSE_PathInfo * create_path_info (const char *path, const struct GNUNET_FS_Uri *uri) { struct GNUNET_FUSE_PathInfo *pi; + GNUNET_HashCode path_hash; + GNUNET_CRYPTO_hash (path, strlen (path), &path_hash); + pi = GNUNET_CONTAINER_multihashmap_get (map, &path_hash); + if (NULL != pi) + return pi; pi = GNUNET_malloc (sizeof (struct GNUNET_FUSE_PathInfo)); pi->path = GNUNET_strdup (path); pi->uri = GNUNET_FS_uri_dup (uri); + GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, + &path_hash, + pi, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + pi->stbuf.st_size = (off_t) GNUNET_FS_uri_chk_get_file_size (uri); + pi->stbuf.st_blocks = 1 + ((pi->stbuf.st_size) / 512); + pi->stbuf.st_blksize = 32 * 1024; + pi->stbuf.st_mode = (S_IRUSR | S_IRGRP | S_IROTH); /* read-only */ + if (0) /* FIXME: test for directory... */ + pi->stbuf.st_mode |= (S_IXUSR | S_IXGRP | S_IXOTH); /* allow traversal */ + pi->stbuf.st_mode |= S_IFREG; /* regular file */ return pi; } @@ -68,6 +85,11 @@ create_path_info (const char *path, const struct GNUNET_FS_Uri *uri) void delete_path_info (struct GNUNET_FUSE_PathInfo *pi) { + if (NULL != pi->tmpfile) + { + GNUNET_break (0 == UNLINK (pi->tmpfile)); + GNUNET_free (pi->tmpfile); + } GNUNET_free (pi->path); GNUNET_FS_uri_destroy (pi->uri); GNUNET_free (pi); @@ -126,7 +148,6 @@ run (void *cls, struct GNUNET_FUSE_PathInfo *pi; struct GNUNET_FS_Uri *uri; char *emsg; - GNUNET_HashCode path_hash; const char *path = "/"; ret = 0; @@ -153,12 +174,7 @@ run (void *cls, } map = GNUNET_CONTAINER_multihashmap_create (10); - GNUNET_CRYPTO_hash (path, strlen (path), &path_hash); pi = create_path_info (path, uri); - GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, - &path_hash, - pi, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); if (GNUNET_YES == single_threaded) diff --git a/src/fuse/gnunet-fuse.h b/src/fuse/gnunet-fuse.h @@ -65,7 +65,7 @@ struct GNUNET_FUSE_PathInfo /** * file attributes */ - struct stat attributes; + struct stat stbuf; }; diff --git a/src/fuse/readdir.c b/src/fuse/readdir.c @@ -1,4 +1,23 @@ /* + This file is part of gnunet-fuse. + (C) 2012 Christian Grothoff (and other contributing authors) + + gnunet-fuse is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + 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 + +*/ +/* * reddir.c - FUSE read directory function * * Created on: Mar 14, 2012 @@ -26,9 +45,9 @@ * * Introduced in version 2.3 */ - #include "gnunet-fuse.h" + static int ret; static int verbose; @@ -217,81 +236,142 @@ readdir_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -int -gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler, - off_t offset, struct fuse_file_info *fi) +static void +download_file (struct GNUNET_FUSE_PathInfo *path_info, + off_t start_offset, + uint64_t length) { - struct GNUNET_FUSE_path_info *path_info = NULL; - printf ("FUSE PATH gives me: `%s'\n", path); - (void) fi; - (void) offset; - - GNUNET_HashCode path_hash; - GNUNET_CRYPTO_hash (path, strlen (path), &path_hash); - /* NOTE: Path can be like /.Trash/1000/files for the trash directory */ - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (map, &path_hash)) - { - /* new path */ - //path_info = create_path_info (path, NULL); - //GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(map, &path_hash, path_info, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - else - { - /* existing path */ - path_info = GNUNET_CONTAINER_multihashmap_get (map, &path_hash); - } - - //GNUNET_assert (path_info != NULL); - -#if 0 - r = GNUNET_malloc (sizeof (struct GNUNET_FUSE_path_info)); - - int len = strlen (path); - int exist = 0; - r->path = path; - - /* compute key */ - - GNUNET_CRYPTO_hash (r->path, len, r->hash); + // FIXME: not implemented... + GNUNET_break (0); +} - exist = GNUNET_CONTAINER_multihashmap_contains (map, r->hash); - if (exist == GNUNET_NO) - { +/** + * Closure for 'process_directory_entry'. + */ +struct DepContext +{ + /** + * Function to call on each entry. + */ + fuse_fill_dir_t filler; + /** + * 'buf' argument to give to filler. + */ + void *buf; -/* Store a key-value pair in the map */ - GNUNET_CONTAINER_multihashmap_put (map, r->hash, r->path, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + /** + * Basepath to add for the entries. + */ + const char *path; +}; -/* store to temporary file */ - r->tmpfile = GNUNET_DISK_mktemp ("gnunet-fuse-tempfile"); -/* find value with given key */ - r->source = GNUNET_CONTAINER_multihashmap_get (map, r->hash); +/** + * Function used to process entries in a directory. + * + * @param cls closure + * @param filename name of the file in the directory + * @param uri URI of the file + * @param metadata metadata for the file; metadata for + * the directory if everything else is NULL/zero + * @param length length of the available data for the file + * (of type size_t since data must certainly fit + * into memory; if files are larger than size_t + * permits, then they will certainly not be + * embedded with the directory itself). + * @param data data available for the file (length bytes) + */ +static void +process_directory_entry (void *cls, + const char *filename, + const struct GNUNET_FS_Uri * + uri, + const struct + GNUNET_CONTAINER_MetaData * + meta, size_t length, + const void *data) +{ + struct DepContext *dc = cls; + struct GNUNET_FUSE_PathInfo *pi; + char *path; + + GNUNET_asprintf (&path, + "%s/%s", + dc->path, + filename); + pi = create_path_info (path, uri); + dc->filler (dc->buf, + filename, + &pi->stbuf, + 0); +} -/* parse uri from given source */ - uri = GNUNET_FS_uri_parse (r->source, &emsg); - GNUNET_SCHEDULER_run (&readdir_task, NULL); - filler (buf, ".", NULL, 0); - filler (buf, "..", NULL, 0); +int +gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + GNUNET_HashCode path_hash; + struct GNUNET_FUSE_PathInfo *path_info; + struct DepContext dc; + size_t size; + int ret; + void *data; + struct GNUNET_DISK_MapHandle *mh; + struct GNUNET_DISK_FileHandle *fh; - return 0; + GNUNET_CRYPTO_hash (path, strlen (path), &path_hash); + path_info = GNUNET_CONTAINER_multihashmap_get (map, &path_hash); + if (NULL == path_info) + { + /* FIXME: we might need to check which of the ancestors + exist and possibly download ancestral directories, + instead of directly giving up here... */ + return - ENOENT; } - + + if (NULL == path_info->tmpfile) + { + /* store to temporary file */ + path_info->tmpfile = GNUNET_DISK_mktemp ("gnunet-fuse-tempfile"); + download_file (path_info, + 0, + GNUNET_FS_uri_chk_get_file_size (path_info->uri)); + } + + + dc.filler = filler; + dc.path = path; + size = (size_t) GNUNET_FS_uri_chk_get_file_size (path_info->uri); + fh = GNUNET_DISK_file_open (path_info->tmpfile, + GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE); + if (NULL == fh) + return -EBADF; + data = GNUNET_DISK_file_map (fh, + &mh, + GNUNET_DISK_MAP_TYPE_READ, + size); + if (NULL == data) + { + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); + return -EBADF; + } + if (GNUNET_OK != + GNUNET_FS_directory_list_contents (size, + data, 0LL, + &process_directory_entry, + &dc)) + ret = - EBADF; else { - uri = GNUNET_FS_uri_parse (r->source, &emsg); - GNUNET_SCHEDULER_run (&readdir_task, NULL); - filler (buf, ".", NULL, 0); filler (buf, "..", NULL, 0); - return 0; + ret = 0; } -#endif - - filler (buf, ".", NULL, 0); - filler (buf, "..", NULL, 0); - return 0; + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_unmap (mh)); + GNUNET_DISK_file_close (fh); + return ret; }