6d97f15536fc734e16f8dcbfa4bdde2aee1a9f78
[oweals/gnunet.git] / src / fs / fs_dirmetascan.c
1 /*
2      This file is part of GNUnet
3      (C) 2005-2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file fs/fs_dirmetascan.c
23  * @brief code to asynchronously build a 'struct GNUNET_FS_ShareTreeItem'
24  *        from an on-disk directory for publishing; use the 'gnunet-helper-fs-publish'.
25  * @author LRN
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
29 #include "gnunet_fs_service.h"
30 #include "gnunet_scheduler_lib.h"
31 #include <pthread.h>
32
33
34 /**
35  * An opaque structure a pointer to which is returned to the
36  * caller to be used to control the scanner.
37  */
38 struct GNUNET_FS_DirScanner
39 {
40
41   /**
42    * Helper process.
43    */
44   struct GNUNET_HELPER_Handle *helper;
45
46   /**
47    * Expanded filename (as given by the scan initiator).
48    * The scanner thread stores a copy here, and frees it when it finishes.
49    */
50   char *filename_expanded;
51
52   /**
53    * Second argument to helper process.
54    */
55   char *ex_arg;
56   
57   /**
58    * The function that will be called every time there's a progress
59    * message.
60    */
61   GNUNET_FS_DirScannerProgressCallback progress_callback;
62   
63   /**
64    * A closure for progress_callback.
65    */
66   void *progress_callback_cls;
67
68   /**
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
71    * scanner.  Must only be manipulated by the thread for the
72    * duration of the thread's runtime.
73    */
74   struct GNUNET_FS_ShareTreeItem *toplevel;
75
76 };
77
78
79
80 /**
81  * Abort the scan.
82  *
83  * @param ds directory scanner structure
84  */
85 void
86 GNUNET_FS_directory_scan_abort (struct GNUNET_FS_DirScanner *ds)
87 {
88   /* terminate helper */
89   GNUNET_HELPER_stop (ds->helper);
90
91   /* free resources */
92   if (NULL != ds->toplevel)
93     GNUNET_FS_share_tree_free (ds->toplevel);
94   GNUNET_free (ds->ex_arg);
95   GNUNET_free (ds->filename_expanded);
96   GNUNET_free (ds);
97 }
98
99
100 /**
101  * Obtain the result of the scan after the scan has signalled
102  * completion.  Must not be called prior to completion.  The 'ds' is
103  * freed as part of this call.
104  *
105  * @param ds directory scanner structure
106  * @return the results of the scan (a directory tree)
107  */
108 struct GNUNET_FS_ShareTreeItem *
109 GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds)
110 {
111   struct GNUNET_FS_ShareTreeItem *result;
112
113   /* check that we're actually done */
114   GNUNET_assert (NULL == ds->helper);
115   /* preserve result */
116   result = ds->toplevel;
117   ds->toplevel = NULL; 
118   GNUNET_FS_directory_scan_abort (ds);
119   return result;
120 }
121
122
123 /**
124  * Called every time there is data to read from the scanner.
125  * Calls the scanner progress handler.
126  *
127  * @param cls the closure (directory scanner object)
128  * @param client always NULL
129  * @param msg message from the helper process
130  */
131 static void
132 process_helper_msgs (void *cls, 
133                      void *client,
134                      const struct GNUNET_MessageHeader *msg)
135 {
136   struct GNUNET_FS_DirScanner *ds = cls;
137   ds++;
138 #if 0
139   enum GNUNET_FS_DirScannerProgressUpdateReason reason;
140   size_t filename_len;
141   int is_directory;
142   char *filename;
143
144   /* Process message. If message is malformed or can't be read, end the scanner */
145   /* read successfully, notify client about progress */
146   ds->progress_callback (ds->progress_callback_cls, 
147                          ds, 
148                          filename,
149                          is_directory, 
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 }
167
168
169 /**
170  * Start a directory scanner thread.
171  *
172  * @param filename name of the directory to scan
173  * @param GNUNET_YES to not to run libextractor on files (only build a tree)
174  * @param ex if not NULL, must be a list of extra plugins for extractor
175  * @param cb the callback to call when there are scanning progress messages
176  * @param cb_cls closure for 'cb'
177  * @return directory scanner object to be used for controlling the scanner
178  */
179 struct GNUNET_FS_DirScanner *
180 GNUNET_FS_directory_scan_start (const char *filename,
181                                 int disable_extractor, const char *ex,
182                                 GNUNET_FS_DirScannerProgressCallback cb, 
183                                 void *cb_cls)
184 {
185   struct stat sbuf;
186   char *filename_expanded;
187   struct GNUNET_FS_DirScanner *ds;
188   char *args[4];
189
190   if (0 != STAT (filename, &sbuf))
191     return NULL;
192   filename_expanded = GNUNET_STRINGS_filename_expand (filename);
193   if (NULL == filename_expanded)
194     return NULL;
195   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
196               "Starting to scan directory `%s'\n",
197               filename_expanded);
198   ds = GNUNET_malloc (sizeof (struct GNUNET_FS_DirScanner));
199   ds->progress_callback = cb;
200   ds->progress_callback_cls = cb_cls;
201   ds->filename_expanded = filename_expanded;
202   ds->ex_arg = GNUNET_strdup ((disable_extractor) ? "-" : ex);
203   args[0] = "gnunet-helper-fs-publish";
204   args[1] = ds->filename_expanded;
205   args[2] = ds->ex_arg;
206   args[3] = NULL;
207   ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish",
208                                     args,
209                                     &process_helper_msgs,
210                                     ds);
211   if (NULL == ds->helper)
212   {
213     GNUNET_free (filename_expanded);
214     GNUNET_free (ds);
215     return NULL;
216   }
217   return ds;
218 }
219
220
221 /* end of fs_dirmetascan.c */