aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_dirmetascan.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-29 21:20:17 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-29 21:20:17 +0000
commitee4d754ebbcc11369dd7e78b50db733e3b921fc2 (patch)
tree547c981117541be04bae9cd18b9bdceeb51be5d9 /src/fs/fs_dirmetascan.c
parent6f912718b1e65181e9e3a62c6c7b8cf32f7d1165 (diff)
downloadgnunet-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.c265
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 */
139static struct GNUNET_FS_ShareTreeItem *
140advance (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 */
183static struct GNUNET_FS_ShareTreeItem *
184expand_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)