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.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/fuse/readdir.c b/src/fuse/readdir.c
new file mode 100644
index 0000000..17145ae
--- /dev/null
+++ b/src/fuse/readdir.c
@@ -0,0 +1,293 @@
1/*
2 * reddir.c - FUSE read directory function
3 *
4 * Created on: Mar 14, 2012
5 * Author: MG, Christian Grothoff, Matthias Wachs,
6 * Krista Bennett, James Blackwell, Igor Wronsky
7 *
8 * Read directory
9 *
10 * This supersedes the old getdir() interface. New applications
11 * should use this.
12 *
13 * The filesystem may choose between two modes of operation:
14 *
15 * 1) The readdir implementation ignores the offset parameter, and
16 * passes zero to the filler function's offset. The filler
17 * function will not return '1' (unless an error happens), so the
18 * whole directory is read in a single readdir operation. This
19 * works just like the old getdir() method.
20 *
21 * 2) The readdir implementation keeps track of the offsets of the
22 * directory entries. It uses the offset parameter and always
23 * passes non-zero offset to the filler function. When the buffer
24 * is full (or an error happens) the filler function will return
25 * '1'.
26 *
27 * Introduced in version 2.3
28 */
29
30#include <sys/types.h>
31#include <sys/mman.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <gnunet-fuse.h>
35#include <gnunet/gnunet_fs_service.h>
36#include <gnunet/gnunet_container_lib.h>
37#include "gnunet/gnunet_crypto_lib.h"
38#include <fuse.h>
39
40static int ret;
41
42static int verbose;
43
44static int delete_incomplete;
45
46static struct GNUNET_FS_DownloadContext *dc;
47
48static unsigned int parallelism = 16;
49
50static unsigned int request_parallelism = 4092;
51
52static int do_recursive;
53
54static int local_only;
55
56static const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58static unsigned int anonymity = 1;
59
60struct GNUNET_FS_Handle *fs;
61
62static struct GNUNET_FS_Handle *ctx;
63
64struct GNUNET_CONTAINER_MultiHashMap *map;
65
66struct GNUNET_FS_Uri *uri;
67
68char *emsg;
69
70struct GNUNET_FUSE_path_info *r;
71
72
73
74
75static void
76cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
77{
78 GNUNET_FS_stop (ctx);
79 ctx = NULL;
80}
81
82static void
83shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
84{
85 struct GNUNET_FS_DownloadContext *d;
86
87 if (dc != NULL)
88 {
89 d = dc;
90 dc = NULL;
91 GNUNET_FS_download_stop (d, delete_incomplete);
92 }
93}
94
95
96/* callback function */
97void *progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo * info)
98{
99
100 char *s;
101 char*s2;
102 char *t;
103
104 switch (info->status)
105 {
106 case GNUNET_FS_STATUS_DOWNLOAD_START:
107 if (verbose > 1)
108 FPRINTF (stderr, _("Starting download `%s'.\n"),
109 info->value.download.filename);
110 break;
111 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
112 if (verbose)
113 {
114 s = GNUNET_STRINGS_relative_time_to_string (info->value.download.eta);
115 if (info->value.download.specifics.progress.block_download_duration.rel_value
116 == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
117 s2 = GNUNET_strdup (_("<unknown time>"));
118 else
119 s2 = GNUNET_STRINGS_relative_time_to_string (
120 info->value.download.specifics.progress.block_download_duration);
121 t = GNUNET_STRINGS_byte_size_fancy (info->value.download.completed *
122 1000LL /
123 (info->value.download.
124 duration.rel_value + 1));
125 FPRINTF (stdout,
126 _("Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to download\n"),
127 info->value.download.filename,
128 (unsigned long long) info->value.download.completed,
129 (unsigned long long) info->value.download.size, s, t, s2);
130 GNUNET_free (s);
131 GNUNET_free (s2);
132 GNUNET_free (t);
133 }
134 break;
135 case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
136 FPRINTF (stderr, _("Error downloading: %s.\n"),
137 info->value.download.specifics.error.message);
138 GNUNET_SCHEDULER_shutdown ();
139 break;
140 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
141 s = GNUNET_STRINGS_byte_size_fancy (info->value.download.completed * 1000 /
142 (info->value.download.
143 duration.rel_value + 1));
144 FPRINTF (stdout, _("Downloading `%s' done (%s/s).\n"),
145 info->value.download.filename, s);
146 GNUNET_free (s);
147 if (info->value.download.dc == dc)
148 GNUNET_SCHEDULER_shutdown ();
149 break;
150 case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
151 if (info->value.download.dc == dc)
152 GNUNET_SCHEDULER_add_continuation (&cleanup_task, NULL,
153 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
154 break;
155 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
156 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
157 break;
158 default:
159 FPRINTF (stderr, _("Unexpected status: %d\n"), info->status);
160 break;
161 }
162
163return NULL;
164}
165
166
167void readdir_task (void *cls,
168 const struct GNUNET_SCHEDULER_TaskContext* tc)
169{
170 enum GNUNET_FS_DownloadOptions options;
171
172 if (NULL == uri)
173 {
174 FPRINTF (stderr, _("Failed to parse URI: %s\n"), emsg);
175 GNUNET_free (emsg);
176 GNUNET_FS_stop (ctx); // ?? hmmm....stop before start ??
177 }
178
179
180 fs = GNUNET_FS_start (cfg, "gnunet-fuse", &progress_cb, NULL,
181 GNUNET_FS_FLAGS_NONE,
182 GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, parallelism,
183 GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, request_parallelism,
184 GNUNET_FS_OPTIONS_END);
185
186 if (NULL == fs)
187 {
188 FPRINTF (stderr, _("Could not initialize `%s' subsystem.\n"), "FS");
189 GNUNET_FS_uri_destroy (uri);
190 ret = 1;
191 return;
192 }
193
194 options = GNUNET_FS_DOWNLOAD_OPTION_NONE;
195 if (do_recursive)
196 options |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
197 if (local_only)
198 options |= GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY;
199
200 struct GNUNET_FS_DownloadContext* dc;
201 dc = GNUNET_FS_download_start (fs, uri, NULL, r->tmpfile, NULL, 0,
202 GNUNET_FS_uri_chk_get_file_size(uri),
203 anonymity, options, NULL, NULL);
204
205 GNUNET_FS_uri_destroy (uri);
206 if (dc == NULL)
207 {
208 GNUNET_FS_stop (ctx);
209 ctx = NULL;
210 return;
211 }
212
213 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL);
214
215}
216
217
218int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
219 off_t offset, struct fuse_file_info *fi)
220{
221 struct GNUNET_FUSE_path_info * path_info = NULL;
222 printf("FUSE PATH gives me: `%s'\n", path);
223 (void) fi;
224 (void) offset;
225
226 GNUNET_HashCode path_hash;
227 GNUNET_CRYPTO_hash (path, strlen (path), &path_hash);
228 /* NOTE: Path can be like /.Trash/1000/files for the trash directory */
229 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(map, &path_hash))
230 {
231 /* new path */
232 //path_info = create_path_info (path, NULL);
233 //GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(map, &path_hash, path_info, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
234 }
235 else
236 {
237 /* existing path */
238 path_info = GNUNET_CONTAINER_multihashmap_get (map, &path_hash);
239 }
240
241 //GNUNET_assert (path_info != NULL);
242
243#if 0
244 r = GNUNET_malloc (sizeof (struct GNUNET_FUSE_path_info));
245
246 int len = strlen(path);
247 int exist = 0;
248 r->path = path;
249
250 /* compute key */
251
252 GNUNET_CRYPTO_hash (r->path, len, r->hash);
253
254
255 exist = GNUNET_CONTAINER_multihashmap_contains (map, r->hash);
256 if ( exist == GNUNET_NO)
257 {
258
259
260/* Store a key-value pair in the map */
261 GNUNET_CONTAINER_multihashmap_put (map, r->hash, r->path, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
262
263/* store to temporary file */
264 r->tmpfile = GNUNET_DISK_mktemp("gnunet-fuse-tempfile");
265
266/* find value with given key */
267 r->source = GNUNET_CONTAINER_multihashmap_get (map, r->hash);
268
269/* parse uri from given source */
270 uri = GNUNET_FS_uri_parse(r->source, &emsg);
271 GNUNET_SCHEDULER_run(&readdir_task, NULL);
272
273 filler(buf, ".", NULL, 0);
274 filler(buf, "..", NULL, 0);
275
276 return 0;
277 }
278
279 else
280 {
281 uri = GNUNET_FS_uri_parse(r->source, &emsg);
282 GNUNET_SCHEDULER_run(&readdir_task, NULL);
283
284 filler(buf, ".", NULL, 0);
285 filler(buf, "..", NULL, 0);
286 return 0;
287 }
288#endif
289
290 filler(buf, ".", NULL, 0);
291 filler(buf, "..", NULL, 0);
292 return 0;
293}