Parcourir la source

Don't enable mmap if file allocation is disabled

Without file allocation, we cannot map file because file length could
be zero.

This could fix bug reported at GH-478
Tatsuhiro Tsujikawa il y a 10 ans
Parent
commit
3974c1223b
3 fichiers modifiés avec 20 ajouts et 9 suppressions
  1. 11 5
      src/AbstractDiskWriter.cc
  2. 5 3
      src/BtFileAllocationEntry.cc
  3. 4 1
      src/StreamFileAllocationEntry.cc

+ 11 - 5
src/AbstractDiskWriter.cc

@@ -284,12 +284,10 @@ ssize_t AbstractDiskWriter::readDataInternal(unsigned char* data, size_t len,
                                              int64_t offset)
 {
   if(mapaddr_) {
-    ssize_t readlen;
-    if(offset > maplen_) {
-      readlen = 0;
-    } else {
-      readlen = std::min(static_cast<size_t>(maplen_ - offset), len);
+    if (offset >= maplen_) {
+      return 0;
     }
+    auto readlen = std::min(maplen_ - offset, static_cast<int64_t>(len));
     memcpy(data, mapaddr_ + offset, readlen);
     return readlen;
   } else {
@@ -355,6 +353,14 @@ void AbstractDiskWriter::ensureMmapWrite(size_t len, int64_t offset)
       }
     } else {
       int64_t filesize = size();
+
+      if (filesize == 0) {
+        // mapping 0 length file is useless.  Also munmap with size ==
+        // 0 will fail with EINVAL.
+        enableMmap_ = false;
+        return;
+      }
+
       int errNum = 0;
       if(static_cast<int64_t>(len + offset) <= filesize) {
 #ifdef __MINGW32__

+ 5 - 3
src/BtFileAllocationEntry.cc

@@ -58,9 +58,11 @@ BtFileAllocationEntry::~BtFileAllocationEntry() {}
 void BtFileAllocationEntry::prepareForNextAction
 (std::vector<std::unique_ptr<Command>>& commands, DownloadEngine* e)
 {
-  BtSetup().setup(commands, getRequestGroup(), e,
-                  getRequestGroup()->getOption().get());
-  if(getRequestGroup()->getOption()->getAsBool(PREF_ENABLE_MMAP)) {
+  auto &option = getRequestGroup()->getOption();
+
+  BtSetup().setup(commands, getRequestGroup(), e, option.get());
+  if(option->getAsBool(PREF_ENABLE_MMAP) &&
+     option->get(PREF_FILE_ALLOCATION) != V_NONE) {
     getRequestGroup()->getPieceStorage()->getDiskAdaptor()->enableMmap();
   }
   if(!getRequestGroup()->downloadFinished()) {

+ 4 - 1
src/StreamFileAllocationEntry.cc

@@ -60,10 +60,13 @@ void StreamFileAllocationEntry::prepareForNextAction
 (std::vector<std::unique_ptr<Command>>& commands,
  DownloadEngine* e)
 {
+  auto &option = getRequestGroup()->getOption();
+
   // For DownloadContext::resetDownloadStartTime(), see also
   // RequestGroup::createInitialCommand()
   getRequestGroup()->getDownloadContext()->resetDownloadStartTime();
-  if(getRequestGroup()->getOption()->getAsBool(PREF_ENABLE_MMAP)) {
+  if(option->getAsBool(PREF_ENABLE_MMAP) &&
+     option->get(PREF_FILE_ALLOCATION) != V_NONE) {
     getRequestGroup()->getPieceStorage()->getDiskAdaptor()->enableMmap();
   }
   if(getNextCommand()) {