diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-29 21:20:17 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-29 21:20:17 +0000 |
commit | ee4d754ebbcc11369dd7e78b50db733e3b921fc2 (patch) | |
tree | 547c981117541be04bae9cd18b9bdceeb51be5d9 /src/fs/fs_dirmetascan.c | |
parent | 6f912718b1e65181e9e3a62c6c7b8cf32f7d1165 (diff) | |
download | gnunet-ee4d754ebbcc11369dd7e78b50db733e3b921fc2.tar.gz gnunet-ee4d754ebbcc11369dd7e78b50db733e3b921fc2.zip |
-towards external meta scanner process
Diffstat (limited to 'src/fs/fs_dirmetascan.c')
-rw-r--r-- | src/fs/fs_dirmetascan.c | 265 |
1 files changed, 228 insertions, 37 deletions
diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c index 6d97f1553..69c7770db 100644 --- a/src/fs/fs_dirmetascan.c +++ b/src/fs/fs_dirmetascan.c | |||
@@ -68,11 +68,20 @@ struct GNUNET_FS_DirScanner | |||
68 | /** | 68 | /** |
69 | * After the scan is finished, it will contain a pointer to the | 69 | * After the scan is finished, it will contain a pointer to the |
70 | * top-level directory entry in the directory tree built by the | 70 | * top-level directory entry in the directory tree built by the |
71 | * scanner. Must only be manipulated by the thread for the | 71 | * scanner. |
72 | * duration of the thread's runtime. | ||
73 | */ | 72 | */ |
74 | struct GNUNET_FS_ShareTreeItem *toplevel; | 73 | struct GNUNET_FS_ShareTreeItem *toplevel; |
75 | 74 | ||
75 | /** | ||
76 | * Current position during processing. | ||
77 | */ | ||
78 | struct GNUNET_FS_ShareTreeItem *pos; | ||
79 | |||
80 | /** | ||
81 | * Arguments for helper. | ||
82 | */ | ||
83 | char *args[4]; | ||
84 | |||
76 | }; | 85 | }; |
77 | 86 | ||
78 | 87 | ||
@@ -121,6 +130,76 @@ GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds) | |||
121 | 130 | ||
122 | 131 | ||
123 | /** | 132 | /** |
133 | * Move in the directory from the given position to the next file | ||
134 | * in DFS traversal. | ||
135 | * | ||
136 | * @param pos current position | ||
137 | * @return next file, NULL for none | ||
138 | */ | ||
139 | static struct GNUNET_FS_ShareTreeItem * | ||
140 | advance (struct GNUNET_FS_ShareTreeItem *pos) | ||
141 | { | ||
142 | int moved; | ||
143 | |||
144 | GNUNET_assert (NULL != pos); | ||
145 | moved = 0; /* must not terminate, even on file, otherwise "normal" */ | ||
146 | while ( (pos->is_directory) || | ||
147 | (0 == moved) ) | ||
148 | { | ||
149 | if ( (moved != -1) && | ||
150 | (NULL != pos->children_head) ) | ||
151 | { | ||
152 | pos = pos->children_head; | ||
153 | moved = 1; /* can terminate if file */ | ||
154 | continue; | ||
155 | } | ||
156 | if (NULL != pos->next) | ||
157 | { | ||
158 | pos = pos->next; | ||
159 | moved = 1; /* can terminate if file */ | ||
160 | continue; | ||
161 | } | ||
162 | if (NULL != pos->parent) | ||
163 | { | ||
164 | pos = pos->parent; | ||
165 | moved = -1; /* force move to 'next' or 'parent' */ | ||
166 | continue; | ||
167 | } | ||
168 | /* no more options, end of traversal */ | ||
169 | return NULL; | ||
170 | } | ||
171 | return pos; | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Add another child node to the tree. | ||
177 | * | ||
178 | * @param parent parent of the child, NULL for top level | ||
179 | * @param filename name of the file or directory | ||
180 | * @param is_directory GNUNET_YES for directories | ||
181 | * @return new entry that was just created | ||
182 | */ | ||
183 | static struct GNUNET_FS_ShareTreeItem * | ||
184 | expand_tree (struct GNUNET_FS_ShareTreeItem *parent, | ||
185 | const char *filename, | ||
186 | int is_directory) | ||
187 | { | ||
188 | struct GNUNET_FS_ShareTreeItem *chld; | ||
189 | |||
190 | chld = GNUNET_malloc (sizeof (struct GNUNET_FS_ShareTreeItem)); | ||
191 | chld->parent = parent; | ||
192 | chld->filename = GNUNET_strdup (filename); | ||
193 | chld->is_directory = is_directory; | ||
194 | if (NULL != parent) | ||
195 | GNUNET_CONTAINER_DLL_insert (parent->children_head, | ||
196 | parent->children_tail, | ||
197 | chld); | ||
198 | return chld; | ||
199 | } | ||
200 | |||
201 | |||
202 | /** | ||
124 | * Called every time there is data to read from the scanner. | 203 | * Called every time there is data to read from the scanner. |
125 | * Calls the scanner progress handler. | 204 | * Calls the scanner progress handler. |
126 | * | 205 | * |
@@ -134,35 +213,145 @@ process_helper_msgs (void *cls, | |||
134 | const struct GNUNET_MessageHeader *msg) | 213 | const struct GNUNET_MessageHeader *msg) |
135 | { | 214 | { |
136 | struct GNUNET_FS_DirScanner *ds = cls; | 215 | struct GNUNET_FS_DirScanner *ds = cls; |
137 | ds++; | 216 | const char *filename; |
138 | #if 0 | 217 | size_t left; |
139 | enum GNUNET_FS_DirScannerProgressUpdateReason reason; | 218 | |
140 | size_t filename_len; | 219 | left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader); |
141 | int is_directory; | 220 | filename = (const char*) &msg[1]; |
142 | char *filename; | 221 | switch (ntohs (msg->type)) |
143 | 222 | { | |
144 | /* Process message. If message is malformed or can't be read, end the scanner */ | 223 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE: |
145 | /* read successfully, notify client about progress */ | 224 | if (filename[left-1] != '\0') |
225 | { | ||
226 | GNUNET_break (0); | ||
227 | break; | ||
228 | } | ||
229 | ds->progress_callback (ds->progress_callback_cls, | ||
230 | filename, GNUNET_NO, | ||
231 | GNUNET_FS_DIRSCANNER_FILE_START); | ||
232 | expand_tree (ds->pos, | ||
233 | filename, GNUNET_NO); | ||
234 | return; | ||
235 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY: | ||
236 | if (filename[left-1] != '\0') | ||
237 | { | ||
238 | GNUNET_break (0); | ||
239 | break; | ||
240 | } | ||
241 | if (0 == strcmp ("..", filename)) | ||
242 | { | ||
243 | if (NULL == ds->pos) | ||
244 | { | ||
245 | GNUNET_break (0); | ||
246 | break; | ||
247 | } | ||
248 | ds->pos = ds->pos->parent; | ||
249 | return; | ||
250 | } | ||
251 | ds->progress_callback (ds->progress_callback_cls, | ||
252 | filename, GNUNET_YES, | ||
253 | GNUNET_FS_DIRSCANNER_FILE_START); | ||
254 | ds->pos = expand_tree (ds->pos, | ||
255 | filename, GNUNET_YES); | ||
256 | if (NULL == ds->toplevel) | ||
257 | ds->toplevel = ds->pos; | ||
258 | return; | ||
259 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR: | ||
260 | break; | ||
261 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE: | ||
262 | if (filename[left-1] != '\0') | ||
263 | break; | ||
264 | ds->progress_callback (ds->progress_callback_cls, | ||
265 | filename, GNUNET_SYSERR, | ||
266 | GNUNET_FS_DIRSCANNER_FILE_IGNORED); | ||
267 | return; | ||
268 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE: | ||
269 | if (0 != left) | ||
270 | { | ||
271 | GNUNET_break (0); | ||
272 | break; | ||
273 | } | ||
274 | ds->progress_callback (ds->progress_callback_cls, | ||
275 | NULL, GNUNET_SYSERR, | ||
276 | GNUNET_FS_DIRSCANNER_ALL_COUNTED); | ||
277 | ds->pos = ds->toplevel; | ||
278 | if (ds->pos->is_directory) | ||
279 | ds->pos = advance (ds->pos); | ||
280 | return; | ||
281 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: | ||
282 | { | ||
283 | size_t nlen; | ||
284 | const char *end; | ||
285 | |||
286 | if (NULL == ds->pos) | ||
287 | { | ||
288 | GNUNET_break (0); | ||
289 | break; | ||
290 | } | ||
291 | end = memchr (filename, 0, left); | ||
292 | if (NULL == end) | ||
293 | { | ||
294 | GNUNET_break (0); | ||
295 | break; | ||
296 | } | ||
297 | end++; | ||
298 | nlen = end - filename; | ||
299 | left -= nlen; | ||
300 | if (0 != strcmp (filename, | ||
301 | ds->pos->filename)) | ||
302 | { | ||
303 | GNUNET_break (0); | ||
304 | break; | ||
305 | } | ||
306 | ds->progress_callback (ds->progress_callback_cls, | ||
307 | filename, GNUNET_YES, | ||
308 | GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED); | ||
309 | if (0 < left) | ||
310 | { | ||
311 | ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, left); | ||
312 | if (NULL == ds->pos->meta) | ||
313 | { | ||
314 | GNUNET_break (0); | ||
315 | break; | ||
316 | } | ||
317 | /* having full filenames is too dangerous; always make sure we clean them up */ | ||
318 | ds->pos->short_filename = GNUNET_strdup (GNUNET_STRINGS_get_short_name (filename)); | ||
319 | GNUNET_CONTAINER_meta_data_delete (ds->pos->meta, | ||
320 | EXTRACTOR_METATYPE_FILENAME, | ||
321 | NULL, 0); | ||
322 | GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "<libgnunetfs>", | ||
323 | EXTRACTOR_METATYPE_FILENAME, | ||
324 | EXTRACTOR_METAFORMAT_UTF8, "text/plain", | ||
325 | ds->pos->short_filename, | ||
326 | strlen (ds->pos->short_filename) + 1); | ||
327 | } | ||
328 | ds->pos = advance (ds->pos); | ||
329 | return; | ||
330 | } | ||
331 | case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED: | ||
332 | if (NULL != ds->pos) | ||
333 | { | ||
334 | GNUNET_break (0); | ||
335 | break; | ||
336 | } | ||
337 | if (0 != left) | ||
338 | { | ||
339 | GNUNET_break (0); | ||
340 | break; | ||
341 | } | ||
342 | ds->progress_callback (ds->progress_callback_cls, | ||
343 | NULL, GNUNET_SYSERR, | ||
344 | GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); | ||
345 | |||
346 | return; | ||
347 | default: | ||
348 | GNUNET_break (0); | ||
349 | break; | ||
350 | } | ||
146 | ds->progress_callback (ds->progress_callback_cls, | 351 | ds->progress_callback (ds->progress_callback_cls, |
147 | ds, | 352 | NULL, GNUNET_SYSERR, |
148 | filename, | 353 | GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); |
149 | is_directory, | 354 | |
150 | reason); | ||
151 | GNUNET_free (filename); | ||
152 | |||
153 | |||
154 | /* having full filenames is too dangerous; always make sure we clean them up */ | ||
155 | item->short_filename = GNUNET_strdup (GNUNET_STRINGS_get_short_name (filename)); | ||
156 | |||
157 | GNUNET_CONTAINER_meta_data_delete (item->meta, | ||
158 | EXTRACTOR_METATYPE_FILENAME, | ||
159 | NULL, 0); | ||
160 | GNUNET_CONTAINER_meta_data_insert (item->meta, "<libgnunetfs>", | ||
161 | EXTRACTOR_METATYPE_FILENAME, | ||
162 | EXTRACTOR_METAFORMAT_UTF8, "text/plain", | ||
163 | item->short_filename, | ||
164 | strlen (item->short_filename) + 1); | ||
165 | #endif | ||
166 | } | 355 | } |
167 | 356 | ||
168 | 357 | ||
@@ -185,7 +374,6 @@ GNUNET_FS_directory_scan_start (const char *filename, | |||
185 | struct stat sbuf; | 374 | struct stat sbuf; |
186 | char *filename_expanded; | 375 | char *filename_expanded; |
187 | struct GNUNET_FS_DirScanner *ds; | 376 | struct GNUNET_FS_DirScanner *ds; |
188 | char *args[4]; | ||
189 | 377 | ||
190 | if (0 != STAT (filename, &sbuf)) | 378 | if (0 != STAT (filename, &sbuf)) |
191 | return NULL; | 379 | return NULL; |
@@ -199,13 +387,16 @@ GNUNET_FS_directory_scan_start (const char *filename, | |||
199 | ds->progress_callback = cb; | 387 | ds->progress_callback = cb; |
200 | ds->progress_callback_cls = cb_cls; | 388 | ds->progress_callback_cls = cb_cls; |
201 | ds->filename_expanded = filename_expanded; | 389 | ds->filename_expanded = filename_expanded; |
202 | ds->ex_arg = GNUNET_strdup ((disable_extractor) ? "-" : ex); | 390 | if (disable_extractor) |
203 | args[0] = "gnunet-helper-fs-publish"; | 391 | ds->ex_arg = GNUNET_strdup ("-"); |
204 | args[1] = ds->filename_expanded; | 392 | else |
205 | args[2] = ds->ex_arg; | 393 | ds->ex_arg = (NULL != ex) ? GNUNET_strdup (ex) : NULL; |
206 | args[3] = NULL; | 394 | ds->args[0] = "gnunet-helper-fs-publish"; |
395 | ds->args[1] = ds->filename_expanded; | ||
396 | ds->args[2] = ds->ex_arg; | ||
397 | ds->args[3] = NULL; | ||
207 | ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish", | 398 | ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish", |
208 | args, | 399 | ds->args, |
209 | &process_helper_msgs, | 400 | &process_helper_msgs, |
210 | ds); | 401 | ds); |
211 | if (NULL == ds->helper) | 402 | if (NULL == ds->helper) |