[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r21775 - gnunet-fuse/src/fuse
From: |
gnunet |
Subject: |
[GNUnet-SVN] r21775 - gnunet-fuse/src/fuse |
Date: |
Wed, 6 Jun 2012 13:44:47 +0200 |
Author: grothoff
Date: 2012-06-06 13:44:47 +0200 (Wed, 06 Jun 2012)
New Revision: 21775
Modified:
gnunet-fuse/src/fuse/getattr.c
gnunet-fuse/src/fuse/gnunet-fuse.c
gnunet-fuse/src/fuse/gnunet-fuse.h
gnunet-fuse/src/fuse/open.c
gnunet-fuse/src/fuse/read.c
gnunet-fuse/src/fuse/readdir.c
Log:
finishing read-only implementation of fuse for 0.9.3
Modified: gnunet-fuse/src/fuse/getattr.c
===================================================================
--- gnunet-fuse/src/fuse/getattr.c 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/getattr.c 2012-06-06 11:44:47 UTC (rev 21775)
@@ -43,10 +43,11 @@
gn_getattr (const char *path, struct stat *stbuf)
{
struct GNUNET_FUSE_PathInfo *pi;
+ int eno;
- pi = GNUNET_FUSE_path_info_get (path);
+ pi = GNUNET_FUSE_path_info_get (path, &eno);
if (NULL == pi)
- return - ENOENT;
+ return - eno;
*stbuf = pi->stbuf;
GNUNET_FUSE_path_info_done (pi);
return 0;
Modified: gnunet-fuse/src/fuse/gnunet-fuse.c
===================================================================
--- gnunet-fuse/src/fuse/gnunet-fuse.c 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/gnunet-fuse.c 2012-06-06 11:44:47 UTC (rev 21775)
@@ -25,6 +25,7 @@
* @author Mauricio Günther
*/
#include "gnunet-fuse.h"
+#include "gfs_download.h"
/**
* Anonymity level to use.
@@ -57,35 +58,181 @@
static char *directory;
/**
- * Global mapping of paths to GNUnet URIs (and file names) for
- * the respective entries.
+ * Root of the file tree.
*/
-static struct GNUNET_CONTAINER_MultiHashMap *map;
+static struct GNUNET_FUSE_PathInfo *root;
+
/**
- * Mutex for synchronizing access to 'map'.
+ * Function used to process entries in a directory; adds the
+ * respective entry to the parent directory.
+ *
+ * @param cls closure with the 'struct GNUNET_FUSE_PathInfo' of the parent
+ * @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 struct GNUNET_Mutex *map_mutex;
+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 GNUNET_FUSE_PathInfo *parent = cls;
+ struct GNUNET_FUSE_PathInfo *pi;
+ int is_directory;
+ if (NULL == filename)
+ return; /* info about the directory itself */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding file `%s' to directory `%s'\n",
+ filename,
+ parent->filename);
+ is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
+ if (GNUNET_SYSERR == is_directory)
+ is_directory = GNUNET_NO; /* if in doubt, say no */
+ pi = GNUNET_FUSE_path_info_create (parent, filename, uri, is_directory);
+ GNUNET_FUSE_path_info_done (pi);
+}
+
/**
+ * Load and parse a directory.
+ *
+ * @param pi path to the directory
+ * @param eno where to store 'errno' on errors
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_FUSE_load_directory (struct GNUNET_FUSE_PathInfo *pi,
+ int * eno)
+{
+ size_t size;
+ void *data;
+ struct GNUNET_DISK_MapHandle *mh;
+ struct GNUNET_DISK_FileHandle *fh;
+
+ /* Need to download directory; store to temporary file */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Downloading directory `%s'\n",
+ pi->filename);
+ pi->tmpfile = GNUNET_DISK_mktemp ("gnunet-fuse-tempfile");
+ if (GNUNET_OK != GNUNET_FUSE_download_file (pi,
+ 0,
+ GNUNET_FS_uri_chk_get_file_size
(pi->uri)))
+ {
+ UNLINK (pi->tmpfile);
+ GNUNET_free (pi->tmpfile);
+ pi->tmpfile = NULL;
+ *eno = EIO; /* low level IO error */
+ return GNUNET_SYSERR;
+ }
+
+ size = (size_t) GNUNET_FS_uri_chk_get_file_size (pi->uri);
+ fh = GNUNET_DISK_file_open (pi->tmpfile,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL == fh)
+ {
+ *eno = EIO;
+ return GNUNET_SYSERR;
+ }
+ 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 - ENOMEM;
+ }
+ *eno = 0;
+ if (GNUNET_OK !=
+ GNUNET_FS_directory_list_contents (size,
+ data, 0LL,
+ &process_directory_entry,
+ pi))
+ *eno = ENOTDIR;
+ GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_unmap (mh));
+ GNUNET_DISK_file_close (fh);
+ if (0 != *eno)
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
+
+/**
* Obtain an existing path info entry from the global map.
*
* @param path path the entry represents
+ * @param eno where to store 'errno' on errors
* @return NULL if no such path entry exists
*/
struct GNUNET_FUSE_PathInfo *
-GNUNET_FUSE_path_info_get (const char *path)
+GNUNET_FUSE_path_info_get (const char *path,
+ int *eno)
{
+ size_t slen = strlen (path) + 1;
+ char buf[slen];
struct GNUNET_FUSE_PathInfo *pi;
- GNUNET_HashCode path_hash;
+ struct GNUNET_FUSE_PathInfo *pos;
+ char *tok;
+
+ memcpy (buf, path, slen);
+ pi = root;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up path `%s'\n",
+ path);
+ GNUNET_mutex_lock (pi->lock);
+ for (tok = strtok (buf, "/"); NULL != tok; tok = strtok (NULL, "/"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Searching for token `%s'\n",
+ tok);
+ if (NULL == pi->tmpfile)
+ {
+ if (GNUNET_OK != GNUNET_FUSE_load_directory (pi, eno))
+ {
+ GNUNET_mutex_unlock (pi->lock);
+ return NULL;
+ }
+ }
- GNUNET_CRYPTO_hash (path, strlen (path), &path_hash);
- GNUNET_mutex_lock (map_mutex);
- pi = GNUNET_CONTAINER_multihashmap_get (map, &path_hash);
- if (NULL != pi)
- ++pi->rc;
- GNUNET_mutex_unlock (map_mutex);
+ pos = pi->child_head;
+ while ( (NULL != pos) &&
+ (0 != strcmp (tok,
+ pos->filename)) )
+ pos = pos->next;
+ if (NULL == pos)
+ {
+ GNUNET_mutex_unlock (pi->lock);
+ *eno = ENOENT;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No file with name `%s' in directory `%s'\n",
+ tok,
+ pi->filename);
+ return NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Descending into directory `%s'\n",
+ tok);
+ GNUNET_mutex_lock (pos->lock);
+ GNUNET_mutex_unlock (pi->lock);
+ pi = pos;
+ }
+ ++pi->rc;
+ GNUNET_mutex_unlock (pi->lock);
return pi;
}
@@ -93,36 +240,37 @@
/**
* Create a new path info entry in the global map.
*
- * @param path path the entry represents
+ * @param parent parent directory (can be NULL)
+ * @param filename name of the file to create
* @param uri URI to use for the path
+ * @param is_directory GNUNET_YES if this entry is for a directory
* @return existing path entry if one already exists, otherwise
- * new path entry with the desired URI
+ * new path entry with the desired URI; in both cases
+ * the reference counter has been incremented by 1
*/
struct GNUNET_FUSE_PathInfo *
-GNUNET_FUSE_path_info_create (const char *path,
+GNUNET_FUSE_path_info_create (struct GNUNET_FUSE_PathInfo *parent,
+ const char *filename,
const struct GNUNET_FS_Uri *uri,
int is_directory)
{
struct GNUNET_FUSE_PathInfo *pi;
- GNUNET_HashCode path_hash;
+ size_t len;
- GNUNET_CRYPTO_hash (path, strlen (path), &path_hash);
- GNUNET_mutex_lock (map_mutex);
- pi = GNUNET_CONTAINER_multihashmap_get (map, &path_hash);
- if (NULL != pi)
+ if (NULL != parent)
{
- GNUNET_mutex_unlock (map_mutex);
- return pi;
+ GNUNET_mutex_lock (parent->lock);
}
+
pi = GNUNET_malloc (sizeof (struct GNUNET_FUSE_PathInfo));
- pi->path = GNUNET_strdup (path);
+ pi->parent = parent;
+ pi->filename = GNUNET_strdup (filename);
+ len = strlen (pi->filename);
+ if ('/' == pi->filename[len - 1])
+ pi->filename[len - 1] = '\0';
pi->uri = GNUNET_FS_uri_dup (uri);
pi->lock = GNUNET_mutex_create (GNUNET_YES);
pi->rc = 1;
- GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map,
- &path_hash,
- pi,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
pi->stbuf.st_mode = (S_IRUSR | S_IRGRP | S_IROTH); /* read-only */
if (GNUNET_YES == is_directory)
{
@@ -133,7 +281,14 @@
pi->stbuf.st_mode |= S_IFREG; /* regular file */
pi->stbuf.st_size = (off_t) GNUNET_FS_uri_chk_get_file_size (uri);
}
- GNUNET_mutex_unlock (map_mutex);
+
+ if (NULL != parent)
+ {
+ GNUNET_CONTAINER_DLL_insert_tail (parent->child_head,
+ parent->child_tail,
+ pi);
+ GNUNET_mutex_unlock (parent->lock);
+ }
return pi;
}
@@ -151,14 +306,14 @@
(void) GNUNET_FUSE_path_info_delete (pi);
return;
}
- GNUNET_mutex_lock (map_mutex);
+ GNUNET_mutex_lock (pi->lock);
--pi->rc;
- GNUNET_mutex_unlock (map_mutex);
+ GNUNET_mutex_unlock (pi->lock);
}
/**
- * Delete a path info entry from the global map (does not actually
+ * Delete a path info entry from the tree (does not actually
* remove anything from the file system). Also decrements the RC.
*
* @param pi entry to remove
@@ -166,19 +321,32 @@
*/
int
GNUNET_FUSE_path_info_delete (struct GNUNET_FUSE_PathInfo *pi)
-{
- GNUNET_HashCode path_hash;
+{
+ struct GNUNET_FUSE_PathInfo *parent = pi->parent;
+ int rc;
int ret;
- int rc;
- GNUNET_CRYPTO_hash (pi->path, strlen (pi->path), &path_hash);
- GNUNET_mutex_lock (map_mutex);
- ret = GNUNET_CONTAINER_multihashmap_remove (map, &path_hash, pi);
+ if (NULL != parent)
+ {
+ ret = 0;
+ GNUNET_mutex_lock (parent->lock);
+ GNUNET_mutex_lock (pi->lock);
+ GNUNET_CONTAINER_DLL_remove (parent->child_head,
+ parent->child_tail,
+ pi);
+ pi->parent = NULL;
+ GNUNET_mutex_unlock (parent->lock);
+ }
+ else
+ {
+ ret = - ENOENT;
+ GNUNET_mutex_lock (pi->lock);
+ }
rc = --pi->rc;
- GNUNET_mutex_unlock (map_mutex);
if (0 != rc)
{
pi->delete_later = GNUNET_YES;
+ GNUNET_mutex_unlock (pi->lock);
}
else
{
@@ -187,33 +355,30 @@
GNUNET_break (0 == UNLINK (pi->tmpfile));
GNUNET_free (pi->tmpfile);
}
- GNUNET_free (pi->path);
+ GNUNET_free (pi->filename);
GNUNET_FS_uri_destroy (pi->uri);
+ GNUNET_mutex_unlock (pi->lock);
GNUNET_mutex_destroy (pi->lock);
GNUNET_free (pi);
}
- if (GNUNET_YES == ret)
- return 0;
- return - ENOENT;
+ return ret;
}
/**
- * Called on each entry in our global 'map' to clean it up.
+ * Called on each node in the path info tree to clean it up.
*
- * @param cls closure, NULL
- * @param key current key code
- * @param value value in the hash map, a 'struct GNUNET_FUSE_PathInfo'
- * @return GNUNET_YES (we should continue to iterate)
+ * @param pi path info to clean up
*/
-static int
-cleanup_path_info (void *cls, const GNUNET_HashCode * key, void *value)
+static void
+cleanup_path_info (struct GNUNET_FUSE_PathInfo *pi)
{
- struct GNUNET_FUSE_PathInfo *pi = value;
+ struct GNUNET_FUSE_PathInfo *pos;
+ while (NULL != (pos = pi->child_head))
+ cleanup_path_info (pos);
++pi->rc;
(void) GNUNET_FUSE_path_info_delete (pi);
- return GNUNET_YES;
}
@@ -249,8 +414,7 @@
int argc;
struct GNUNET_FS_Uri *uri;
char *emsg;
- const char *path = "/";
- struct GNUNET_FUSE_PathInfo *pi;
+ int eno;
cfg = c;
ret = 0;
@@ -279,20 +443,31 @@
(GNUNET_YES != GNUNET_FS_uri_test_loc (uri)) )
{
fprintf (stderr,
- _("The given URI is not for a directory and can thus not be
mounted\n"),
- emsg);
+ _("The given URI is not for a directory and can thus not be
mounted\n"));
ret = 4;
+ GNUNET_FS_uri_destroy (uri);
return;
}
- map_mutex = GNUNET_mutex_create (GNUNET_NO);
- map = GNUNET_CONTAINER_multihashmap_create (1024);
- pi = GNUNET_FUSE_path_info_create (path, uri, GNUNET_YES);
+ root = GNUNET_FUSE_path_info_create (NULL, "/", uri, GNUNET_YES);
+ if (GNUNET_OK !=
+ GNUNET_FUSE_load_directory (root, &eno))
+ {
+ fprintf (stderr,
+ _("Failed to mount `%s': %s\n"),
+ source,
+ STRERROR (eno));
+ ret = 5;
+ cleanup_path_info (root);
+ GNUNET_FS_uri_destroy (uri);
+ return;
+ }
if (GNUNET_YES == single_threaded)
argc = 5;
else
argc = 2;
+
{
char *a[argc + 1];
a[0] = "gnunet-fuse";
@@ -306,12 +481,7 @@
a[argc] = NULL;
fuse_main (argc, a, &fops, NULL);
}
- GNUNET_FUSE_path_info_done (pi);
- GNUNET_CONTAINER_multihashmap_iterate (map, &cleanup_path_info, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (map);
- map = NULL;
- GNUNET_mutex_destroy (map_mutex);
- map_mutex = NULL;
+ cleanup_path_info (root);
GNUNET_FS_uri_destroy (uri);
}
Modified: gnunet-fuse/src/fuse/gnunet-fuse.h
===================================================================
--- gnunet-fuse/src/fuse/gnunet-fuse.h 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/gnunet-fuse.h 2012-06-06 11:44:47 UTC (rev 21775)
@@ -52,9 +52,37 @@
*/
struct GNUNET_FUSE_PathInfo
{
+
/**
- * uri to corresponding path
+ * All files in a directory are kept in a DLL.
*/
+ struct GNUNET_FUSE_PathInfo *next;
+
+ /**
+ * All files in a directory are kept in a DLL.
+ */
+ struct GNUNET_FUSE_PathInfo *prev;
+
+ /**
+ * Parent directory, NULL for the root.
+ */
+ struct GNUNET_FUSE_PathInfo *parent;
+
+ /**
+ * Head of linked list of entries in this directory
+ * (NULL if this is a file).
+ */
+ struct GNUNET_FUSE_PathInfo *child_head;
+
+ /**
+ * Head of linked list of entries in this directory
+ * (NULL if this is a file).
+ */
+ struct GNUNET_FUSE_PathInfo *child_tail;
+
+ /**
+ * URI of the file or directory.
+ */
struct GNUNET_FS_Uri *uri;
/**
@@ -63,14 +91,15 @@
struct GNUNET_CONTAINER_MetaData *meta;
/**
- * pathname
+ * Name of the file for this path (i.e. "home"). '/' for the root (all other
+ * filenames must not contain '/')
*/
- char* path;
+ char *filename;
/**
- * name of temporary file
+ * Name of temporary file, NULL if we never accessed this file or directory.
*/
- char* tmpfile;
+ char *tmpfile;
/**
* file attributes
@@ -78,13 +107,26 @@
struct stat stbuf;
/**
- * Lock for exclusive access to this struct.
+ * Lock for exclusive access to this struct (i.e. for downloading blocks).
+ * Lock order: always lock parents before children.
*/
struct GNUNET_Mutex *lock;
/**
- * Reference counter.
+ * Beginning of a contiguous range of blocks of the file what we
+ * have downloaded already to 'tmpfile'.
*/
+ uint64_t download_start;
+
+ /**
+ * End of a contiguous range of blocks of the file what we
+ * have downloaded already to 'tmpfile'.
+ */
+ uint64_t download_end;
+
+ /**
+ * Reference counter (used if the file is deleted while being opened, etc.)
+ */
unsigned int rc;
/**
@@ -97,7 +139,8 @@
/**
* Create a new path info entry in the global map.
*
- * @param path path the entry represents
+ * @param parent parent directory (can be NULL)
+ * @param filename name of the file to create
* @param uri URI to use for the path
* @param is_directory GNUNET_YES if this entry is for a directory
* @return existing path entry if one already exists, otherwise
@@ -105,7 +148,8 @@
* the reference counter has been incremented by 1
*/
struct GNUNET_FUSE_PathInfo *
-GNUNET_FUSE_path_info_create (const char *path,
+GNUNET_FUSE_path_info_create (struct GNUNET_FUSE_PathInfo *parent,
+ const char *filename,
const struct GNUNET_FS_Uri *uri,
int is_directory);
@@ -114,11 +158,13 @@
* Obtain an existing path info entry from the global map.
*
* @param path path the entry represents
+ * @param eno where to store 'errno' on errors
* @return NULL if no such path entry exists, otherwise
* an entry with incremented reference counter (!)
*/
struct GNUNET_FUSE_PathInfo *
-GNUNET_FUSE_path_info_get (const char *path);
+GNUNET_FUSE_path_info_get (const char *path,
+ int *eno);
/**
@@ -141,9 +187,30 @@
GNUNET_FUSE_path_info_delete (struct GNUNET_FUSE_PathInfo *pi);
+/**
+ * Load and parse a directory.
+ *
+ * @param pi path to the directory
+ * @param eno where to store 'errno' on errors
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_FUSE_load_directory (struct GNUNET_FUSE_PathInfo *pi,
+ int * eno);
+
+
/* FUSE function files */
int gn_getattr(const char *path, struct stat *stbuf);
+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_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);
@@ -156,19 +223,11 @@
int gn_truncate(const char *path, off_t size);
-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]);
Modified: gnunet-fuse/src/fuse/open.c
===================================================================
--- gnunet-fuse/src/fuse/open.c 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/open.c 2012-06-06 11:44:47 UTC (rev 21775)
@@ -54,10 +54,13 @@
gn_open (const char *path, struct fuse_file_info *fi)
{
struct GNUNET_FUSE_PathInfo *pi;
+ int eno;
- pi = GNUNET_FUSE_path_info_get (path);
+ pi = GNUNET_FUSE_path_info_get (path, &eno);
if (NULL == pi)
- return - ENOENT;
+ return - eno;
+ /* NOTE: once we allow writes, we need to keep the RC
+ incremented until close... */
GNUNET_FUSE_path_info_done (pi);
if (O_RDONLY != (fi->flags & 3))
return - EACCES;
Modified: gnunet-fuse/src/fuse/read.c
===================================================================
--- gnunet-fuse/src/fuse/read.c 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/read.c 2012-06-06 11:44:47 UTC (rev 21775)
@@ -52,15 +52,22 @@
struct GNUNET_FUSE_PathInfo *path_info;
uint64_t fsize;
struct GNUNET_DISK_FileHandle *fh;
+ int eno;
- path_info = GNUNET_FUSE_path_info_get (path);
+ path_info = GNUNET_FUSE_path_info_get (path, &eno);
if (NULL == path_info)
+ return - eno;
+ fsize = GNUNET_FS_uri_chk_get_file_size (path_info->uri);
+ if (offset > fsize)
{
- /* FIXME: we might need to check which of the ancestors
- exist and possibly download ancestral directories,
- instead of directly giving up here... */
- return - ENOENT;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No data available at offset %llu of file `%s'\n",
+ (unsigned long long) offset,
+ path);
+ return 0;
+ }
+ if (offset + size > fsize)
+ size = fsize - offset;
if (NULL == path_info->tmpfile)
{
/* store to temporary file */
@@ -76,8 +83,46 @@
return - EIO; /* low level IO error */
}
}
+ else
+ {
+ if ( (offset < path_info->download_start) ||
+ (size + offset > path_info->download_end) )
+ {
+ /* need to download some more... */
+ if (GNUNET_OK != GNUNET_FUSE_download_file (path_info,
+ offset,
+ size))
+ {
+ UNLINK (path_info->tmpfile);
+ GNUNET_free (path_info->tmpfile);
+ path_info->tmpfile = NULL;
+ GNUNET_FUSE_path_info_done (path_info);
+ return - EIO; /* low level IO error */
+ }
+ }
+ }
+ /* combine ranges */
+ if (path_info->download_start == path_info->download_end)
+ {
+ /* first range */
+ path_info->download_start = offset;
+ path_info->download_end = offset + size;
+ }
+ else
+ {
+ /* only combine ranges if the resulting range would
+ be contiguous... */
+ if ( (offset >= path_info->download_start) &&
+ (offset <= path_info->download_end) &&
+ (offset + size > path_info->download_end) )
+ path_info->download_end = offset + size;
+ if ( (offset + size >= path_info->download_start) &&
+ (offset + size <= path_info->download_end) &&
+ (offset < path_info->download_start) )
+ path_info->download_start = offset;
+ }
- fsize = 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);
Modified: gnunet-fuse/src/fuse/readdir.c
===================================================================
--- gnunet-fuse/src/fuse/readdir.c 2012-06-06 10:54:07 UTC (rev 21774)
+++ gnunet-fuse/src/fuse/readdir.c 2012-06-06 11:44:47 UTC (rev 21775)
@@ -53,153 +53,29 @@
#include "gnunet-fuse.h"
#include "gfs_download.h"
-/**
- * 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;
-
- /**
- * Basepath to add for the entries.
- */
- const char *path;
-};
-
-
-/**
- * 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;
- int is_directory;
-
- if (NULL == filename)
- return; /* info about the directory itself */
- GNUNET_asprintf (&path,
- "%s%s",
- dc->path,
- filename);
- is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
- if (GNUNET_SYSERR == is_directory)
- is_directory = GNUNET_NO; /* if in doubt, say no */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Listing filename `%s' in directory `%s' (%s)\n",
- filename,
- dc->path,
- path);
- pi = GNUNET_FUSE_path_info_create (path, uri, is_directory);
- dc->filler (dc->buf,
- filename,
- &pi->stbuf,
- 0);
- GNUNET_FUSE_path_info_done (pi);
-}
-
-
int
gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
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;
+ struct GNUNET_FUSE_PathInfo *pos;
+ int eno;
- path_info = GNUNET_FUSE_path_info_get (path);
+ path_info = GNUNET_FUSE_path_info_get (path, &eno);
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");
- if (GNUNET_OK != GNUNET_FUSE_download_file (path_info,
- 0,
-
GNUNET_FS_uri_chk_get_file_size (path_info->uri)))
- {
- UNLINK (path_info->tmpfile);
- GNUNET_free (path_info->tmpfile);
- path_info->tmpfile = NULL;
- GNUNET_FUSE_path_info_done (path_info);
- return - EIO; /* low level IO error */
- }
- }
-
- dc.filler = filler;
- dc.path = path;
- dc.buf = buf;
- 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)
- {
- GNUNET_FUSE_path_info_done (path_info);
- 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));
- GNUNET_FUSE_path_info_done (path_info);
- return -EBADF;
- }
+ return - eno;
+ if ( (NULL == path_info->tmpfile) &&
+ (GNUNET_OK != GNUNET_FUSE_load_directory (path_info, &eno)) )
+ return - eno;
filler (buf, ".", NULL, 0);
filler (buf, "..", NULL, 0);
- ret = 0;
- if (GNUNET_OK !=
- GNUNET_FS_directory_list_contents (size,
- data, 0LL,
- &process_directory_entry,
- &dc))
- ret = - EIO;
- GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_unmap (mh));
- GNUNET_DISK_file_close (fh);
+ for (pos = path_info->child_head; NULL != pos; pos = pos->next)
+ filler (buf, pos->filename,
+ &pos->stbuf,
+ 0);
GNUNET_FUSE_path_info_done (path_info);
- return ret;
+ return 0;
}
/* end of readdir.c */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r21775 - gnunet-fuse/src/fuse,
gnunet <=