diff --git a/ChangeLog b/ChangeLog index 934e8d8b..72c56334 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-05-03 Tatsuhiro Tsujikawa + + Fixed the bug that read-only file with wrong file size will cause + error because it cannot be truncated to the correct size. Now if + file size is different than the expected one, re-open file in + writable mode. + * src/AbstractSingleDiskAdaptor.cc + * src/AbstractSingleDiskAdaptor.h + * src/BtCheckIntegrityEntry.cc + * src/DiskAdaptor.h + * src/MultiDiskAdaptor.h + * src/RequestGroup.cc + 2009-05-03 Tatsuhiro Tsujikawa Fixed the bug that with --check-integrity option aria2 reports diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc index f1c71493..695eab7c 100644 --- a/src/AbstractSingleDiskAdaptor.cc +++ b/src/AbstractSingleDiskAdaptor.cc @@ -42,7 +42,8 @@ namespace aria2 { -AbstractSingleDiskAdaptor::AbstractSingleDiskAdaptor():totalLength(0) {} +AbstractSingleDiskAdaptor::AbstractSingleDiskAdaptor(): + totalLength(0), _readOnly(false) {} AbstractSingleDiskAdaptor::~AbstractSingleDiskAdaptor() {} @@ -126,11 +127,13 @@ bool AbstractSingleDiskAdaptor::directIOAllowed() const void AbstractSingleDiskAdaptor::enableReadOnly() { diskWriter->enableReadOnly(); + _readOnly = true; } void AbstractSingleDiskAdaptor::disableReadOnly() { diskWriter->disableReadOnly(); + _readOnly = false; } void AbstractSingleDiskAdaptor::cutTrailingGarbage() diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h index b01f29a2..f8c9e3a1 100644 --- a/src/AbstractSingleDiskAdaptor.h +++ b/src/AbstractSingleDiskAdaptor.h @@ -46,6 +46,7 @@ class AbstractSingleDiskAdaptor : public DiskAdaptor { protected: SharedHandle diskWriter; uint64_t totalLength; + bool _readOnly; public: AbstractSingleDiskAdaptor(); @@ -84,6 +85,8 @@ public: // Make sure that DiskWriter is set before calling this function. virtual void disableReadOnly(); + virtual bool isReadOnlyEnabled() const { return _readOnly; } + virtual void cutTrailingGarbage(); virtual std::string getFilePath() = 0; diff --git a/src/BtCheckIntegrityEntry.cc b/src/BtCheckIntegrityEntry.cc index 1be5e251..211467c2 100644 --- a/src/BtCheckIntegrityEntry.cc +++ b/src/BtCheckIntegrityEntry.cc @@ -51,11 +51,14 @@ BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {} void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque& commands, DownloadEngine* e) { - // Now reopen DiskAdaptor with read only disabled. - _requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); - _requestGroup->getPieceStorage()->getDiskAdaptor()->disableReadOnly(); - _requestGroup->getPieceStorage()->getDiskAdaptor()->openFile(); - + const SharedHandle& diskAdaptor = + _requestGroup->getPieceStorage()->getDiskAdaptor(); + if(diskAdaptor->isReadOnlyEnabled()) { + // Now reopen DiskAdaptor with read only disabled. + diskAdaptor->closeFile(); + diskAdaptor->disableReadOnly(); + diskAdaptor->openFile(); + } SharedHandle entry (new BtFileAllocationEntry(_requestGroup)); proceedFileAllocation(commands, entry, e); diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index a07d42e0..959f430b 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -100,6 +100,8 @@ public: virtual void disableReadOnly() {} + virtual bool isReadOnlyEnabled() const { return false; } + // Assumed each file length is stored in fileEntries or DiskAdaptor knows it. // If each actual file's length is larger than that, truncate file to that // length. diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index ae9695e7..21fa60a6 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -155,6 +155,8 @@ public: virtual void disableReadOnly(); + virtual bool isReadOnlyEnabled() const { return _readOnly; } + void setPieceLength(size_t pieceLength) { this->pieceLength = pieceLength; } diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index a33d179c..d65a687d 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -311,7 +311,20 @@ void RequestGroup::createInitialCommand(std::deque& commands, } } _progressInfoFile = progressInfoFile; - + { + uint64_t actualFileSize = _pieceStorage->getDiskAdaptor()->size(); + if(actualFileSize != btContext->getTotalLength()) { + // Re-open file in writable mode to allow the program + // truncate the file to the specified length + _logger->debug("File size not match. Re-open file in writable mode." + " Expected:%s Actual:%s", + Util::uitos(btContext->getTotalLength()).c_str(), + Util::uitos(actualFileSize).c_str()); + _pieceStorage->getDiskAdaptor()->closeFile(); + _pieceStorage->getDiskAdaptor()->disableReadOnly(); + _pieceStorage->getDiskAdaptor()->openFile(); + } + } if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) { std::deque commands; DHTSetup().setup(commands, e, _option); @@ -371,7 +384,7 @@ void RequestGroup::processCheckIntegrityEntry(std::deque& commands, if(e->option->getAsBool(PREF_CHECK_INTEGRITY) && entry->isValidationReady()) { entry->initValidator(); - entry->cutTrailingGarbage(); + entry->cutTrailingGarbage(); e->_checkIntegrityMan->pushEntry(entry); } else #endif // ENABLE_MESSAGE_DIGEST