2 This file is part of GNUnet.
3 (C) 2003, 2004, 2006 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file fs/fs_unindex.c
23 * @author Krista Bennett
24 * @author Christian Grothoff
25 * @brief Unindex file.
28 * - code cleanup (share more with upload.c)
32 #include "gnunet_fs_service.h"
36 * Iterate over all indexed files.
38 * @param h handle to the file sharing subsystem
39 * @param iterator function to call on each indexed file
40 * @param iterator_cls closure for iterator
43 GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
44 GNUNET_FS_IndexedFileProcessor iterator,
53 * @param h handle to the file sharing subsystem
54 * @param filename file to unindex
55 * @return NULL on error, otherwise handle
57 struct GNUNET_FS_UnindexContext *
58 GNUNET_FS_unindex (struct GNUNET_FS_Handle *h,
66 * Clean up after completion of an unindex operation.
71 GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
79 #define STRICT_CHECKS GNUNET_NO
82 * Append the given key and query to the iblock[level].
83 * If iblock[level] is already full, compute its chk
84 * and push it to level+1. iblocks is guaranteed to
87 * This function matches exactly upload.c::pushBlock,
88 * except in the call to 'GNUNET_FS_delete'. TODO: refactor
89 * to avoid code duplication (move to block.c, pass
90 * GNUNET_FS_delete as argument!).
93 pushBlock (struct GNUNET_ClientServerConnection *sock,
94 const GNUNET_EC_ContentHashKey * chk, unsigned int level,
95 GNUNET_DatastoreValue ** iblocks)
99 GNUNET_DatastoreValue *value;
100 GNUNET_EC_DBlock *db;
101 GNUNET_EC_ContentHashKey ichk;
103 size = ntohl (iblocks[level]->size) - sizeof (GNUNET_DatastoreValue);
105 (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
106 db = (GNUNET_EC_DBlock *) & iblocks[level][1];
107 if (present == GNUNET_ECRS_CHK_PER_INODE)
109 GNUNET_EC_file_block_get_key (db, size, &ichk.key);
110 GNUNET_EC_file_block_get_query (db, size, &ichk.query);
111 if (GNUNET_OK != pushBlock (sock, &ichk, level + 1, iblocks))
113 GNUNET_GE_BREAK (NULL, 0);
114 return GNUNET_SYSERR;
116 GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
118 if (GNUNET_SYSERR == GNUNET_FS_delete (sock, value))
121 GNUNET_GE_BREAK (NULL, 0);
122 return GNUNET_SYSERR;
125 GNUNET_FS_delete (sock, value);
128 size = sizeof (GNUNET_EC_DBlock);
130 /* append GNUNET_EC_ContentHashKey */
131 memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
132 iblocks[level]->size = htonl (size +
133 sizeof (GNUNET_EC_ContentHashKey) +
134 sizeof (GNUNET_DatastoreValue));
141 * Undo sym-linking operation:
142 * a) check if we have a symlink
143 * b) delete symbolic link
146 undoSymlinking (struct GNUNET_GE_Context *ectx,
148 const GNUNET_HashCode * fileId,
149 struct GNUNET_ClientServerConnection *sock)
158 return GNUNET_OK; /* symlinks do not exist? */
160 if (0 != LSTAT (fn, &buf))
162 GNUNET_GE_LOG_STRERROR_FILE (ectx,
163 GNUNET_GE_ERROR | GNUNET_GE_BULK |
164 GNUNET_GE_USER | GNUNET_GE_ADMIN, "stat",
166 return GNUNET_SYSERR;
169 if (!S_ISLNK (buf.st_mode))
173 GNUNET_get_daemon_configuration_value (sock, "FS", "INDEX-DIRECTORY");
174 if (serverDir == NULL)
176 serverFN = GNUNET_malloc (strlen (serverDir) + 2 + sizeof (GNUNET_EncName));
177 strcpy (serverFN, serverDir);
178 GNUNET_free (serverDir);
179 if (serverFN[strlen (serverFN) - 1] != DIR_SEPARATOR)
180 strcat (serverFN, DIR_SEPARATOR_STR);
181 GNUNET_hash_to_enc (fileId, &enc);
182 strcat (serverFN, (char *) &enc);
184 if (0 != UNLINK (serverFN))
186 GNUNET_GE_LOG_STRERROR_FILE (ectx,
187 GNUNET_GE_ERROR | GNUNET_GE_BULK |
188 GNUNET_GE_USER | GNUNET_GE_ADMIN, "unlink",
190 GNUNET_free (serverFN);
191 return GNUNET_SYSERR;
193 GNUNET_free (serverFN);
202 * @return GNUNET_SYSERR if the unindexing failed (i.e. not indexed)
205 GNUNET_ECRS_file_unindex (struct GNUNET_GE_Context *ectx,
206 struct GNUNET_GC_Configuration *cfg,
207 const char *filename,
208 GNUNET_ECRS_UploadProgressCallback upcb,
209 void *upcbClosure, GNUNET_ECRS_TestTerminate tt,
212 unsigned long long filesize;
213 unsigned long long pos;
214 unsigned int treedepth;
218 GNUNET_DatastoreValue **iblocks;
219 GNUNET_DatastoreValue *dblock;
220 GNUNET_EC_DBlock *db;
221 GNUNET_DatastoreValue *value;
222 struct GNUNET_ClientServerConnection *sock;
223 GNUNET_HashCode fileId;
224 GNUNET_EC_ContentHashKey chk;
226 GNUNET_CronTime start;
230 start = GNUNET_get_time ();
231 if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
233 GNUNET_GE_BREAK (ectx, 0);
234 return GNUNET_SYSERR;
237 GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
238 return GNUNET_SYSERR;
239 sock = GNUNET_client_connection_create (ectx, cfg);
241 return GNUNET_SYSERR;
244 upcb (filesize, 0, eta, upcbClosure);
245 if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
247 GNUNET_client_connection_destroy (sock);
248 GNUNET_GE_BREAK (ectx, 0);
249 return GNUNET_SYSERR;
251 now = GNUNET_get_time ();
252 eta = now + 2 * (now - start);
253 /* very rough estimate: GNUNET_hash reads once through the file,
254 we'll do that once more and write it. But of course
255 the second read may be cached, and we have the encryption,
256 so a factor of two is really, really just a rough estimate */
258 /* reset the counter since the formula later does not
259 take the time for GNUNET_hash_file into account */
260 treedepth = GNUNET_ECRS_compute_depth (filesize);
262 /* Test if file is indexed! */
263 wasIndexed = GNUNET_FS_test_indexed (sock, &fileId);
265 fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
268 GNUNET_client_connection_destroy (sock);
269 return GNUNET_SYSERR;
272 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
273 sizeof (GNUNET_EC_DBlock));
275 htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
276 sizeof (GNUNET_EC_DBlock));
277 dblock->anonymity_level = htonl (0);
278 dblock->priority = htonl (0);
279 dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
280 dblock->expiration_time = GNUNET_htonll (0);
281 db = (GNUNET_EC_DBlock *) & dblock[1];
282 db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
284 GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
285 for (i = 0; i <= treedepth; i++)
288 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
289 GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
291 htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
292 iblocks[i]->anonymity_level = htonl (0);
293 iblocks[i]->priority = htonl (0);
294 iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
295 iblocks[i]->expiration_time = GNUNET_htonll (0);
296 ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
297 htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
301 while (pos < filesize)
304 upcb (filesize, pos, eta, upcbClosure);
306 if (GNUNET_OK != tt (ttClosure))
308 size = GNUNET_ECRS_DBLOCK_SIZE;
309 if (size > filesize - pos)
311 size = filesize - pos;
312 memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
315 htonl (sizeof (GNUNET_DatastoreValue) + size +
316 sizeof (GNUNET_EC_DBlock));
317 if (size != READ (fd, &db[1], size))
319 GNUNET_GE_LOG_STRERROR_FILE (ectx,
320 GNUNET_GE_ERROR | GNUNET_GE_USER |
321 GNUNET_GE_ADMIN | GNUNET_GE_BULK,
326 if (GNUNET_OK != tt (ttClosure))
328 GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
330 GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
332 if (GNUNET_OK != pushBlock (sock, &chk, 0, /* dblocks are on level 0 */
335 GNUNET_GE_BREAK (ectx, 0);
341 GNUNET_EC_file_block_encode (db, size, &chk.query, &value))
343 *value = *dblock; /* copy options! */
345 if (GNUNET_OK != GNUNET_FS_delete (sock, value))
348 GNUNET_GE_BREAK (ectx, 0);
352 GNUNET_FS_delete (sock, value);
362 now = GNUNET_get_time ();
363 eta = (GNUNET_CronTime) (start +
364 (((double) (now - start) / (double) pos))
365 * (double) filesize);
368 if (GNUNET_OK != tt (ttClosure))
370 for (i = 0; i < treedepth; i++)
372 size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
373 db = (GNUNET_EC_DBlock *) & iblocks[i][1];
374 GNUNET_EC_file_block_get_key (db, size, &chk.key);
375 GNUNET_EC_file_block_get_query (db, size, &chk.query);
376 if (GNUNET_OK != pushBlock (sock, &chk, i + 1, iblocks))
378 GNUNET_GE_BREAK (ectx, 0);
381 GNUNET_EC_file_block_encode (db, size, &chk.query, &value);
383 if (GNUNET_OK != GNUNET_FS_delete (sock, value))
386 GNUNET_GE_BREAK (ectx, 0);
390 GNUNET_FS_delete (sock, value);
393 GNUNET_free (iblocks[i]);
399 if (GNUNET_OK == undoSymlinking (ectx, filename, &fileId, sock))
402 GNUNET_FS_unindex (sock, GNUNET_ECRS_DBLOCK_SIZE, &fileId))
404 GNUNET_GE_BREAK (ectx, 0);
410 GNUNET_GE_BREAK (ectx, 0);
414 GNUNET_free (iblocks[treedepth]);
416 GNUNET_free (iblocks);
417 GNUNET_free (dblock);
419 GNUNET_client_connection_destroy (sock);
422 for (i = 0; i <= treedepth; i++)
423 GNUNET_free_non_null (iblocks[i]);
424 GNUNET_free (iblocks);
425 GNUNET_free (dblock);
427 GNUNET_client_connection_destroy (sock);
428 return GNUNET_SYSERR;
433 /* end of fs_unindex.c */