+/**
+ * Helper function to setup the download context.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param uri the URI of the file (determines what to download); CHK or LOC URI
+ * @param meta known metadata for the file (can be NULL)
+ * @param filename where to store the file, maybe NULL (then no file is
+ * created on disk and data must be grabbed from the callbacks)
+ * @param tempname where to store temporary file data, not used if filename is non-NULL;
+ * can be NULL (in which case we will pick a name if needed); the temporary file
+ * may already exist, in which case we will try to use the data that is there and
+ * if it is not what is desired, will overwrite it
+ * @param offset at what offset should we start the download (typically 0)
+ * @param length how many bytes should be downloaded starting at offset
+ * @param anonymity anonymity level to use for the download
+ * @param options various options
+ * @param cctx initial value for the client context for this download
+ * @return context that can be used to control this download
+ */
+struct GNUNET_FS_DownloadContext *
+create_download_context (struct GNUNET_FS_Handle *h,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ const char *filename, const char *tempname,
+ uint64_t offset, uint64_t length, uint32_t anonymity,
+ enum GNUNET_FS_DownloadOptions options, void *cctx)
+{
+ struct GNUNET_FS_DownloadContext *dc;
+
+ GNUNET_assert (GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri));
+ if ((offset + length < offset) ||
+ (offset + length > GNUNET_FS_uri_chk_get_file_size (uri)))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ dc = GNUNET_malloc (sizeof (struct GNUNET_FS_DownloadContext));
+ dc->h = h;
+ dc->uri = GNUNET_FS_uri_dup (uri);
+ dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ dc->client_info = cctx;
+ dc->start_time = GNUNET_TIME_absolute_get ();
+ if (NULL != filename)
+ {
+ dc->filename = GNUNET_strdup (filename);
+ if (GNUNET_YES == GNUNET_DISK_file_test (filename))
+ GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES));
+ }
+ if (GNUNET_FS_uri_test_loc (dc->uri))
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_FS_uri_loc_get_peer_identity (dc->uri, &dc->target));
+ dc->offset = offset;
+ dc->length = length;
+ dc->anonymity = anonymity;
+ dc->options = options;
+ dc->active =
+ GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE));
+ dc->treedepth =
+ GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri));
+ if ((NULL == filename) && (is_recursive_download (dc)))
+ {
+ if (NULL != tempname)
+ dc->temp_filename = GNUNET_strdup (tempname);
+ else
+ dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp");
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting download `%s' of %llu bytes with tree depth %u\n",
+ filename,
+ (unsigned long long) length,
+ dc->treedepth);
+ dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc);
+ return dc;
+}
+
+