Do not crash if key is NULL.
[oweals/gnunet.git] / src / fs / fs_download.c
index 070be010609601ec5e492e5d9dda1a47499b6b46..f8933bb9dbf4f840717441fd8ce75884eed825bb 100644 (file)
@@ -450,6 +450,18 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
     return;
   if (dr->depth > 0)
   {
+    if ( (dc->offset > 0) ||
+         (dc->length < GNUNET_ntohll (dc->uri->data.chk.file_length)) )
+    {
+      /* NOTE: this test is not tight, but should suffice; the issue
+         here is that 'dr->num_children' may inherently only specify a
+         smaller range than what is in the original file;
+         thus, reconstruction of (some) inner blocks will fail.
+         FIXME: we might eventually want to write a tighter test to
+         maximize the circumstances under which we do succeed with
+         IBlock reconstruction. (need good tests though). */
+      return;
+    }
     complete = GNUNET_YES;
     for (i = 0; i < dr->num_children; i++)
     {
@@ -494,39 +506,43 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
     }
     /* write block to disk */
     fn = (NULL != dc->filename) ? dc->filename : dc->temp_filename;
-    fh = GNUNET_DISK_file_open (fn,
-                                GNUNET_DISK_OPEN_READWRITE |
-                                GNUNET_DISK_OPEN_CREATE |
-                                GNUNET_DISK_OPEN_TRUNCATE,
-                                GNUNET_DISK_PERM_USER_READ |
-                                GNUNET_DISK_PERM_USER_WRITE |
-                                GNUNET_DISK_PERM_GROUP_READ |
-                                GNUNET_DISK_PERM_OTHER_READ);
-    if (NULL == fh)
-    {
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
-      GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"),
-                       fn);
-      GNUNET_DISK_file_close (fh);
-      dr->state = BRS_ERROR;
-      pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR;
-      pi.value.download.specifics.error.message = dc->emsg;
-      GNUNET_FS_download_make_status_ (&pi, dc);
-      return;
-    }
-    if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len))
+    if (NULL != fn)
     {
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
-      GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"),
-                       fn);
+      fh = GNUNET_DISK_file_open (fn,
+                                  GNUNET_DISK_OPEN_READWRITE |
+                                  GNUNET_DISK_OPEN_CREATE |
+                                  GNUNET_DISK_OPEN_TRUNCATE,
+                                  GNUNET_DISK_PERM_USER_READ |
+                                  GNUNET_DISK_PERM_USER_WRITE |
+                                  GNUNET_DISK_PERM_GROUP_READ |
+                                  GNUNET_DISK_PERM_OTHER_READ);
+      if (NULL == fh)
+      {
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
+        GNUNET_asprintf (&dc->emsg,
+                         _("Failed to open file `%s' for writing"),
+                         fn);
+        GNUNET_DISK_file_close (fh);
+        dr->state = BRS_ERROR;
+        pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR;
+        pi.value.download.specifics.error.message = dc->emsg;
+        GNUNET_FS_download_make_status_ (&pi, dc);
+        return;
+      }
+      if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len))
+      {
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
+        GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"),
+                         fn);
+        GNUNET_DISK_file_close (fh);
+        dr->state = BRS_ERROR;
+        pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR;
+        pi.value.download.specifics.error.message = dc->emsg;
+        GNUNET_FS_download_make_status_ (&pi, dc);
+        return;
+      }
       GNUNET_DISK_file_close (fh);
-      dr->state = BRS_ERROR;
-      pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR;
-      pi.value.download.specifics.error.message = dc->emsg;
-      GNUNET_FS_download_make_status_ (&pi, dc);
-      return;
     }
-    GNUNET_DISK_file_close (fh);
     /* signal success */
     dr->state = BRS_DOWNLOAD_UP;
     dc->completed = dc->length;
@@ -934,7 +950,7 @@ GNUNET_FS_free_download_request_ (struct DownloadRequest *dr)
  * @param cls closure (our 'struct ProcessResultClosure')
  * @param key query for the given value / request
  * @param value value in the hash map (a 'struct DownloadRequest')
- * @return GNUNET_YES (we should continue to iterate); unless serious error
+ * @return #GNUNET_YES (we should continue to iterate); unless serious error
  */
 static int
 process_result_with_request (void *cls, const struct GNUNET_HashCode * key,
@@ -1492,7 +1508,7 @@ activate_fs_download (void *cls, struct GNUNET_CLIENT_Connection *client)
 /**
  * We must stop to ask the FS service for our blocks.  Pause the download.
  *
- * @param cls the 'struct GNUNET_FS_DownloadContext'
+ * @param cls the `struct GNUNET_FS_DownloadContext`
  */
 static void
 deactivate_fs_download (void *cls)
@@ -1550,7 +1566,7 @@ create_download_request (struct DownloadRequest *parent,
   unsigned int head_skip;
   uint64_t child_block_size;
 
-  dr = GNUNET_malloc (sizeof (struct DownloadRequest));
+  dr = GNUNET_new (struct DownloadRequest);
   dr->parent = parent;
   dr->depth = depth;
   dr->offset = dr_offset;
@@ -2081,7 +2097,7 @@ create_download_context (struct GNUNET_FS_Handle *h,
     GNUNET_break (0);
     return NULL;
   }
-  dc = GNUNET_malloc (sizeof (struct GNUNET_FS_DownloadContext));
+  dc = GNUNET_new (struct GNUNET_FS_DownloadContext);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Starting download %p, %u bytes at offset %llu\n",
              dc,