aboutsummaryrefslogtreecommitdiff
path: root/src/fuse/readdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fuse/readdir.c')
-rw-r--r--src/fuse/readdir.c148
1 files changed, 12 insertions, 136 deletions
diff --git a/src/fuse/readdir.c b/src/fuse/readdir.c
index 9cb914b..32bd10d 100644
--- a/src/fuse/readdir.c
+++ b/src/fuse/readdir.c
@@ -53,153 +53,29 @@
53#include "gnunet-fuse.h" 53#include "gnunet-fuse.h"
54#include "gfs_download.h" 54#include "gfs_download.h"
55 55
56/**
57 * Closure for 'process_directory_entry'.
58 */
59struct DepContext
60{
61 /**
62 * Function to call on each entry.
63 */
64 fuse_fill_dir_t filler;
65
66 /**
67 * 'buf' argument to give to filler.
68 */
69 void *buf;
70
71 /**
72 * Basepath to add for the entries.
73 */
74 const char *path;
75};
76
77
78/**
79 * Function used to process entries in a directory.
80 *
81 * @param cls closure
82 * @param filename name of the file in the directory
83 * @param uri URI of the file
84 * @param metadata metadata for the file; metadata for
85 * the directory if everything else is NULL/zero
86 * @param length length of the available data for the file
87 * (of type size_t since data must certainly fit
88 * into memory; if files are larger than size_t
89 * permits, then they will certainly not be
90 * embedded with the directory itself).
91 * @param data data available for the file (length bytes)
92 */
93static void
94process_directory_entry (void *cls,
95 const char *filename,
96 const struct GNUNET_FS_Uri *
97 uri,
98 const struct
99 GNUNET_CONTAINER_MetaData *
100 meta, size_t length,
101 const void *data)
102{
103 struct DepContext *dc = cls;
104 struct GNUNET_FUSE_PathInfo *pi;
105 char *path;
106 int is_directory;
107
108 if (NULL == filename)
109 return; /* info about the directory itself */
110 GNUNET_asprintf (&path,
111 "%s%s",
112 dc->path,
113 filename);
114 is_directory = GNUNET_FS_meta_data_test_for_directory (meta);
115 if (GNUNET_SYSERR == is_directory)
116 is_directory = GNUNET_NO; /* if in doubt, say no */
117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
118 "Listing filename `%s' in directory `%s' (%s)\n",
119 filename,
120 dc->path,
121 path);
122 pi = GNUNET_FUSE_path_info_create (path, uri, is_directory);
123 dc->filler (dc->buf,
124 filename,
125 &pi->stbuf,
126 0);
127 GNUNET_FUSE_path_info_done (pi);
128}
129
130 56
131int 57int
132gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler, 58gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
133 off_t offset, struct fuse_file_info *fi) 59 off_t offset, struct fuse_file_info *fi)
134{ 60{
135 struct GNUNET_FUSE_PathInfo *path_info; 61 struct GNUNET_FUSE_PathInfo *path_info;
136 struct DepContext dc; 62 struct GNUNET_FUSE_PathInfo *pos;
137 size_t size; 63 int eno;
138 int ret;
139 void *data;
140 struct GNUNET_DISK_MapHandle *mh;
141 struct GNUNET_DISK_FileHandle *fh;
142 64
143 path_info = GNUNET_FUSE_path_info_get (path); 65 path_info = GNUNET_FUSE_path_info_get (path, &eno);
144 if (NULL == path_info) 66 if (NULL == path_info)
145 { 67 return - eno;
146 /* FIXME: we might need to check which of the ancestors 68 if ( (NULL == path_info->tmpfile) &&
147 exist and possibly download ancestral directories, 69 (GNUNET_OK != GNUNET_FUSE_load_directory (path_info, &eno)) )
148 instead of directly giving up here... */ 70 return - eno;
149 return - ENOENT;
150 }
151
152 if (NULL == path_info->tmpfile)
153 {
154 /* store to temporary file */
155 path_info->tmpfile = GNUNET_DISK_mktemp ("gnunet-fuse-tempfile");
156 if (GNUNET_OK != GNUNET_FUSE_download_file (path_info,
157 0,
158 GNUNET_FS_uri_chk_get_file_size (path_info->uri)))
159 {
160 UNLINK (path_info->tmpfile);
161 GNUNET_free (path_info->tmpfile);
162 path_info->tmpfile = NULL;
163 GNUNET_FUSE_path_info_done (path_info);
164 return - EIO; /* low level IO error */
165 }
166 }
167
168 dc.filler = filler;
169 dc.path = path;
170 dc.buf = buf;
171 size = (size_t) GNUNET_FS_uri_chk_get_file_size (path_info->uri);
172 fh = GNUNET_DISK_file_open (path_info->tmpfile,
173 GNUNET_DISK_OPEN_READ,
174 GNUNET_DISK_PERM_NONE);
175 if (NULL == fh)
176 {
177 GNUNET_FUSE_path_info_done (path_info);
178 return -EBADF;
179 }
180 data = GNUNET_DISK_file_map (fh,
181 &mh,
182 GNUNET_DISK_MAP_TYPE_READ,
183 size);
184 if (NULL == data)
185 {
186 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
187 GNUNET_FUSE_path_info_done (path_info);
188 return -EBADF;
189 }
190 filler (buf, ".", NULL, 0); 71 filler (buf, ".", NULL, 0);
191 filler (buf, "..", NULL, 0); 72 filler (buf, "..", NULL, 0);
192 ret = 0; 73 for (pos = path_info->child_head; NULL != pos; pos = pos->next)
193 if (GNUNET_OK != 74 filler (buf, pos->filename,
194 GNUNET_FS_directory_list_contents (size, 75 &pos->stbuf,
195 data, 0LL, 76 0);
196 &process_directory_entry,
197 &dc))
198 ret = - EIO;
199 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_unmap (mh));
200 GNUNET_DISK_file_close (fh);
201 GNUNET_FUSE_path_info_done (path_info); 77 GNUNET_FUSE_path_info_done (path_info);
202 return ret; 78 return 0;
203} 79}
204 80
205/* end of readdir.c */ 81/* end of readdir.c */