+deserialize_download (struct GNUNET_FS_Handle *h,
+ struct GNUNET_BIO_ReadHandle *rh,
+ struct GNUNET_FS_DownloadContext *parent,
+ struct GNUNET_FS_SearchResult *search,
+ const char *serialization);
+
+
+/**
+ * Deserialize a search.
+ *
+ * @param h overall context
+ * @param rh file to deserialize from
+ * @param psearch_result parent search result
+ * @param serialization name under which the search was serialized
+ */
+static struct GNUNET_FS_SearchContext *
+deserialize_search (struct GNUNET_FS_Handle *h,
+ struct GNUNET_BIO_ReadHandle *rh,
+ struct GNUNET_FS_SearchResult *psearch_result,
+ const char *serialization);
+
+
+/**
+ * Function called with a filename of serialized search result
+ * to deserialize.
+ *
+ * @param cls the 'struct GNUNET_FS_SearchContext*'
+ * @param filename complete filename (absolute path)
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+deserialize_search_result (void *cls, const char *filename)
+{
+ struct GNUNET_FS_SearchContext *sc = cls;
+ char *ser;
+ char *uris;
+ char *emsg;
+ char *download;
+ char *update_srch;
+ struct GNUNET_BIO_ReadHandle *rh;
+ struct GNUNET_BIO_ReadHandle *drh;
+ struct GNUNET_FS_SearchResult *sr;
+
+ ser = get_serialization_short_name (filename);
+ rh = GNUNET_BIO_read_open (filename);
+ if (rh == NULL)
+ {
+ if (ser != NULL)
+ {
+ remove_sync_file_in_dir (sc->h,
+ (sc->psearch_result ==
+ NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH :
+ GNUNET_FS_SYNC_PATH_CHILD_SEARCH,
+ sc->serialization, ser);
+ GNUNET_free (ser);
+ }
+ return GNUNET_OK;
+ }
+ emsg = NULL;
+ uris = NULL;
+ download = NULL;
+ update_srch = NULL;
+ sr = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchResult));
+ sr->serialization = ser;
+ if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "result-uri", &uris, 10 * 1024))
+ || (NULL == (sr->uri = GNUNET_FS_uri_parse (uris, &emsg))) ||
+ (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-lnk", &download, 16))
+ || (GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "search-lnk", &update_srch, 16)) ||
+ (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "result-meta", &sr->meta)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_read (rh, "result-key", &sr->key, sizeof (GNUNET_HashCode)))
+ || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->mandatory_missing)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->optional_support)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_success)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_trials)))
+ {
+ GNUNET_break (0);
+ goto cleanup;
+ }
+ GNUNET_free (uris);
+ if (download != NULL)
+ {
+ drh = get_read_handle (sc->h, GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD, download);
+ if (drh != NULL)
+ {
+ deserialize_download (sc->h, drh, NULL, sr, download);
+ if (GNUNET_OK != GNUNET_BIO_read_close (drh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to resume sub-download `%s': %s\n"), download,
+ emsg);
+ GNUNET_free (emsg);
+ }
+ }
+ GNUNET_free (download);
+ }
+ if (update_srch != NULL)
+ {
+ drh =
+ get_read_handle (sc->h, GNUNET_FS_SYNC_PATH_CHILD_SEARCH, update_srch);
+ if (drh != NULL)
+ {
+ deserialize_search (sc->h, drh, sr, update_srch);
+ if (GNUNET_OK != GNUNET_BIO_read_close (drh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to resume sub-search `%s': %s\n"), update_srch,
+ emsg);
+ GNUNET_free (emsg);
+ }
+ }
+ GNUNET_free (update_srch);
+ }
+ GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &sr->key, sr,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failure while resuming search operation `%s': %s\n"),
+ filename, emsg);
+ GNUNET_free (emsg);
+ }
+ return GNUNET_OK;
+cleanup:
+ GNUNET_free_non_null (download);
+ GNUNET_free_non_null (emsg);
+ GNUNET_free_non_null (uris);
+ GNUNET_free_non_null (update_srch);
+ if (sr->uri != NULL)
+ GNUNET_FS_uri_destroy (sr->uri);
+ if (sr->meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (sr->meta);
+ GNUNET_free (sr->serialization);
+ GNUNET_free (sr);
+ if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failure while resuming search operation `%s': %s\n"),
+ filename, emsg);
+ GNUNET_free (emsg);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Send the 'resume' signal to the callback; also actually
+ * resume the download (put it in the queue). Does this
+ * recursively for the top-level download and all child
+ * downloads.
+ *
+ * @param dc download to resume
+ */
+static void
+signal_download_resume (struct GNUNET_FS_DownloadContext *dc)
+{
+ struct GNUNET_FS_DownloadContext *dcc;
+ struct GNUNET_FS_ProgressInfo pi;
+
+ pi.status = GNUNET_FS_STATUS_DOWNLOAD_RESUME;
+ pi.value.download.specifics.resume.meta = dc->meta;
+ pi.value.download.specifics.resume.message = dc->emsg;
+ GNUNET_FS_download_make_status_ (&pi, dc);
+ dcc = dc->child_head;
+ while (NULL != dcc)
+ {
+ signal_download_resume (dcc);
+ dcc = dcc->next;
+ }
+ if (dc->pending_head != NULL)
+ GNUNET_FS_download_start_downloading_ (dc);
+}
+
+
+/**
+ * Signal resuming of a search to our clients (for the
+ * top level search and all sub-searches).
+ *
+ * @param sc search being resumed
+ */
+static void
+signal_search_resume (struct GNUNET_FS_SearchContext *sc);
+
+
+/**
+ * Iterator over search results signaling resume to the client for
+ * each result.
+ *
+ * @param cls closure, the 'struct GNUNET_FS_SearchContext'
+ * @param key current key code
+ * @param value value in the hash map, the 'struct GNUNET_FS_SearchResult'
+ * @return GNUNET_YES (we should continue to iterate)
+ */
+static int
+signal_result_resume (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct GNUNET_FS_SearchContext *sc = cls;
+ struct GNUNET_FS_ProgressInfo pi;
+ struct GNUNET_FS_SearchResult *sr = value;
+
+ if (0 == sr->mandatory_missing)
+ {
+ pi.status = GNUNET_FS_STATUS_SEARCH_RESUME_RESULT;
+ pi.value.search.specifics.resume_result.meta = sr->meta;
+ pi.value.search.specifics.resume_result.uri = sr->uri;
+ pi.value.search.specifics.resume_result.result = sr;
+ pi.value.search.specifics.resume_result.availability_rank =
+ 2 * sr->availability_success - sr->availability_trials;
+ pi.value.search.specifics.resume_result.availability_certainty =
+ sr->availability_trials;
+ pi.value.search.specifics.resume_result.applicability_rank =
+ sr->optional_support;
+ sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
+ }
+ if (sr->download != NULL)
+ {
+ signal_download_resume (sr->download);
+ }
+ else
+ {
+ GNUNET_FS_search_start_probe_ (sr);
+ }
+ if (sr->update_search != NULL)
+ signal_search_resume (sr->update_search);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Free memory allocated by the search context and its children
+ *
+ * @param sc search context to free
+ */
+static void
+free_search_context (struct GNUNET_FS_SearchContext *sc);
+
+
+/**
+ * Iterator over search results freeing each.
+ *
+ * @param cls closure, the 'struct GNUNET_FS_SearchContext'
+ * @param key current key code
+ * @param value value in the hash map, the 'struct GNUNET_FS_SearchResult'
+ * @return GNUNET_YES (we should continue to iterate)
+ */
+static int
+free_result (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct GNUNET_FS_SearchResult *sr = value;
+
+ if (sr->update_search != NULL)
+ {
+ free_search_context (sr->update_search);
+ GNUNET_assert (NULL == sr->update_search);
+ }
+ GNUNET_CONTAINER_meta_data_destroy (sr->meta);
+ GNUNET_FS_uri_destroy (sr->uri);
+ GNUNET_free (sr);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Free memory allocated by the search context and its children
+ *
+ * @param sc search context to free
+ */
+static void
+free_search_context (struct GNUNET_FS_SearchContext *sc)
+{
+ if (sc->serialization != NULL)
+ {
+ GNUNET_FS_remove_sync_file_ (sc->h,
+ (sc->psearch_result ==
+ NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH :
+ GNUNET_FS_SYNC_PATH_CHILD_SEARCH,
+ sc->serialization);
+ GNUNET_FS_remove_sync_dir_ (sc->h,
+ (sc->psearch_result ==
+ NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH :
+ GNUNET_FS_SYNC_PATH_CHILD_SEARCH,
+ sc->serialization);
+ }
+ GNUNET_free_non_null (sc->serialization);
+ GNUNET_free_non_null (sc->emsg);
+ if (sc->uri != NULL)
+ GNUNET_FS_uri_destroy (sc->uri);
+ if (sc->master_result_map != NULL)
+ {
+ GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &free_result,
+ sc);
+ GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map);
+ }
+ GNUNET_free (sc);
+}
+
+
+/**
+ * Function called with a filename of serialized sub-download
+ * to deserialize.
+ *
+ * @param cls the 'struct GNUNET_FS_DownloadContext*' (parent)
+ * @param filename complete filename (absolute path)
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+deserialize_subdownload (void *cls, const char *filename)
+{
+ struct GNUNET_FS_DownloadContext *parent = cls;
+ char *ser;
+ char *emsg;
+ struct GNUNET_BIO_ReadHandle *rh;
+
+ ser = get_serialization_short_name (filename);
+ rh = GNUNET_BIO_read_open (filename);
+ if (rh == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _
+ ("Failed to resume sub-download `%s': could not open file `%s'\n"),
+ ser, filename);
+ GNUNET_free (ser);
+ return GNUNET_OK;
+ }
+ deserialize_download (parent->h, rh, parent, NULL, ser);
+ if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to resume sub-download `%s': %s\n"), ser, emsg);
+ GNUNET_free (emsg);
+ }
+ GNUNET_free (ser);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Free this download context and all of its descendants.
+ * (only works during deserialization since not all possible
+ * state it taken care of).
+ *
+ * @param dc context to free
+ */
+static void
+free_download_context (struct GNUNET_FS_DownloadContext *dc)
+{
+ struct GNUNET_FS_DownloadContext *dcc;
+
+ if (dc->meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (dc->meta);
+ if (dc->uri != NULL)
+ GNUNET_FS_uri_destroy (dc->uri);
+ GNUNET_free_non_null (dc->temp_filename);
+ GNUNET_free_non_null (dc->emsg);
+ GNUNET_free_non_null (dc->filename);
+ GNUNET_free_non_null (dc->serialization);
+ while (NULL != (dcc = dc->child_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (dc->child_head, dc->child_tail, dcc);
+ free_download_context (dcc);
+ }
+ GNUNET_FS_free_download_request_ (dc->top_request);
+ if (NULL != dc->active)
+ GNUNET_CONTAINER_multihashmap_destroy (dc->active);
+ GNUNET_free (dc);
+}
+
+
+/**
+ * Deserialize a download.
+ *
+ * @param h overall context
+ * @param rh file to deserialize from
+ * @param parent parent download
+ * @param search associated search
+ * @param serialization name under which the search was serialized
+ */
+static void
+deserialize_download (struct GNUNET_FS_Handle *h,
+ struct GNUNET_BIO_ReadHandle *rh,
+ struct GNUNET_FS_DownloadContext *parent,
+ struct GNUNET_FS_SearchResult *search,
+ const char *serialization)
+{
+ struct GNUNET_FS_DownloadContext *dc;
+ char *emsg;
+ char *uris;
+ char *dn;
+ uint32_t options;
+ uint32_t status;
+
+ uris = NULL;
+ emsg = NULL;
+ dc = GNUNET_malloc (sizeof (struct GNUNET_FS_DownloadContext));
+ dc->parent = parent;
+ dc->h = h;
+ dc->serialization = GNUNET_strdup (serialization);
+ if ((GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "download-uri", &uris, 10 * 1024)) ||
+ (NULL == (dc->uri = GNUNET_FS_uri_parse (uris, &emsg))) ||
+ ((GNUNET_YES != GNUNET_FS_uri_test_chk (dc->uri)) &&
+ (GNUNET_YES != GNUNET_FS_uri_test_loc (dc->uri))) ||
+ (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "download-meta", &dc->meta))
+ || (GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "download-emsg", &dc->emsg, 10 * 1024)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "download-fn", &dc->filename, 10 * 1024)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "download-tfn", &dc->temp_filename,
+ 10 * 1024)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->old_file_size)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->offset)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->length)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->completed)) ||
+ (GNUNET_OK != read_start_time (rh, &dc->start_time)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dc->anonymity)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &status)))
+ {
+ GNUNET_break (0);
+ goto cleanup;
+ }
+ dc->options = (enum GNUNET_FS_DownloadOptions) options;
+ dc->active =
+ GNUNET_CONTAINER_multihashmap_create (1 + 2 * (dc->length / DBLOCK_SIZE));
+ dc->has_finished = (int) status;
+ dc->treedepth =
+ GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri));
+ if (GNUNET_FS_uri_test_loc (dc->uri))
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_FS_uri_loc_get_peer_identity (dc->uri, &dc->target));
+ if (dc->emsg == NULL)
+ {
+ dc->top_request = read_download_request (rh);
+ if (dc->top_request == NULL)
+ {
+ GNUNET_break (0);
+ goto cleanup;
+ }
+ }
+ dn = get_download_sync_filename (dc, dc->serialization, ".dir");
+ if (dn != NULL)
+ {
+ if (GNUNET_YES == GNUNET_DISK_directory_test (dn))
+ GNUNET_DISK_directory_scan (dn, &deserialize_subdownload, dc);
+ GNUNET_free (dn);
+ }
+ if (parent != NULL)
+ {
+ abort (); // for debugging for now
+ GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc);
+ }
+ if (search != NULL)
+ {
+ dc->search = search;
+ search->download = dc;
+ }
+ if ((parent == NULL) && (search == NULL))
+ {
+ dc->top =
+ GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc);
+ signal_download_resume (dc);
+ }
+ GNUNET_free (uris);
+ dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc);
+ return;
+cleanup:
+ GNUNET_free_non_null (uris);
+ GNUNET_free_non_null (emsg);
+ free_download_context (dc);
+}
+
+
+/**
+ * Signal resuming of a search to our clients (for the
+ * top level search and all sub-searches).
+ *
+ * @param sc search being resumed
+ */
+static void
+signal_search_resume (struct GNUNET_FS_SearchContext *sc)
+{
+ struct GNUNET_FS_ProgressInfo pi;
+
+ pi.status = GNUNET_FS_STATUS_SEARCH_RESUME;
+ pi.value.search.specifics.resume.message = sc->emsg;
+ pi.value.search.specifics.resume.is_paused =
+ (sc->client == NULL) ? GNUNET_YES : GNUNET_NO;
+ sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
+ GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map,
+ &signal_result_resume, sc);
+
+}
+
+
+/**
+ * Deserialize a search.
+ *
+ * @param h overall context
+ * @param rh file to deserialize from
+ * @param psearch_result parent search result
+ * @param serialization name under which the search was serialized
+ */
+static struct GNUNET_FS_SearchContext *
+deserialize_search (struct GNUNET_FS_Handle *h,
+ struct GNUNET_BIO_ReadHandle *rh,
+ struct GNUNET_FS_SearchResult *psearch_result,
+ const char *serialization)
+{
+ struct GNUNET_FS_SearchContext *sc;
+ char *emsg;
+ char *uris;
+ char *dn;
+ uint32_t options;
+ char in_pause;
+
+ if ((psearch_result != NULL) && (psearch_result->update_search != NULL))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ uris = NULL;
+ emsg = NULL;
+ sc = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchContext));
+ if (psearch_result != NULL)
+ {
+ sc->psearch_result = psearch_result;
+ psearch_result->update_search = sc;
+ }
+ sc->h = h;
+ sc->serialization = GNUNET_strdup (serialization);
+ if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "search-uri", &uris, 10 * 1024))
+ || (NULL == (sc->uri = GNUNET_FS_uri_parse (uris, &emsg))) ||
+ ((GNUNET_YES != GNUNET_FS_uri_test_ksk (sc->uri)) &&
+ (GNUNET_YES != GNUNET_FS_uri_test_sks (sc->uri))) ||
+ (GNUNET_OK != read_start_time (rh, &sc->start_time)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_read_string (rh, "search-emsg", &sc->emsg, 10 * 1024)) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_read (rh, "search-pause", &in_pause, sizeof (in_pause))) ||
+ (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sc->anonymity)))
+ {
+ GNUNET_break (0);
+ goto cleanup;
+ }
+ sc->options = (enum GNUNET_FS_SearchOptions) options;
+ sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16);
+ dn = get_serialization_file_name_in_dir (h,
+ (sc->psearch_result ==
+ NULL) ?
+ GNUNET_FS_SYNC_PATH_MASTER_SEARCH :
+ GNUNET_FS_SYNC_PATH_CHILD_SEARCH,
+ sc->serialization, "");
+ if (dn != NULL)
+ {
+ if (GNUNET_YES == GNUNET_DISK_directory_test (dn))
+ GNUNET_DISK_directory_scan (dn, &deserialize_search_result, sc);
+ GNUNET_free (dn);
+ }
+ if (('\0' == in_pause) &&
+ (GNUNET_OK != GNUNET_FS_search_start_searching_ (sc)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _
+ ("Could not resume running search, will resume as paused search\n"));
+ }
+ signal_search_resume (sc);
+ GNUNET_free (uris);
+ return sc;
+cleanup:
+ GNUNET_free_non_null (emsg);
+ free_search_context (sc);
+ GNUNET_free_non_null (uris);
+ return NULL;
+}
+
+
+/**
+ * Function called with a filename of serialized search operation
+ * to deserialize.
+ *
+ * @param cls the 'struct GNUNET_FS_Handle*'
+ * @param filename complete filename (absolute path)
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+deserialize_search_file (void *cls, const char *filename)
+{
+ struct GNUNET_FS_Handle *h = cls;
+ char *ser;
+ char *emsg;
+ struct GNUNET_BIO_ReadHandle *rh;
+ struct GNUNET_FS_SearchContext *sc;
+
+ ser = get_serialization_short_name (filename);
+ rh = GNUNET_BIO_read_open (filename);
+ if (rh == NULL)
+ {
+ if (ser != NULL)
+ {
+ GNUNET_FS_remove_sync_file_ (h, GNUNET_FS_SYNC_PATH_MASTER_SEARCH, ser);
+ GNUNET_free (ser);
+ }
+ return GNUNET_OK;
+ }
+ sc = deserialize_search (h, rh, NULL, ser);
+ if (sc != NULL)
+ sc->top = GNUNET_FS_make_top (h, &GNUNET_FS_search_signal_suspend_, sc);
+ GNUNET_free (ser);
+ if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failure while resuming search operation `%s': %s\n"),
+ filename, emsg);
+ GNUNET_free (emsg);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called with a filename of serialized download operation
+ * to deserialize.
+ *
+ * @param cls the 'struct GNUNET_FS_Handle*'
+ * @param filename complete filename (absolute path)
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+deserialize_download_file (void *cls, const char *filename)
+{
+ struct GNUNET_FS_Handle *h = cls;
+ char *ser;
+ char *emsg;
+ struct GNUNET_BIO_ReadHandle *rh;
+
+ ser = get_serialization_short_name (filename);
+ rh = GNUNET_BIO_read_open (filename);
+ if (rh == NULL)
+ {
+ if (0 != UNLINK (filename))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
+ GNUNET_free (ser);
+ return GNUNET_OK;
+ }
+ deserialize_download (h, rh, NULL, NULL, ser);
+ GNUNET_free (ser);
+ if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failure while resuming download operation `%s': %s\n"),
+ filename, emsg);
+ GNUNET_free (emsg);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Deserialize informatin about pending operations.
+ *
+ * @param master_path which master directory should be scanned
+ * @param proc function to call for each entry (will get 'h' for 'cls')
+ * @param h the 'struct GNUNET_FS_Handle*'
+ */
+static void
+deserialization_master (const char *master_path, GNUNET_FileNameCallback proc,
+ struct GNUNET_FS_Handle *h)