diff --git a/ChangeLog b/ChangeLog index 47994cde..c730622e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2006-03-24 Tatsuhiro Tsujikawa + + * Request.h: Added AFTER_COMPLETED event. + * TorrentDownloadEngine.cc: Prints "Download complete" message + instead of downloaded size and progress(%) after download completes. + * PeerInteractionCommand.cc: After download completes, sends unchoke + message to the peer if it is interested in what localhost has + downloaded. + * TorrentMan.cc: In single-file mode, copy temporary file to the final + destination instead of just renaming it. + * TorrentMan.cc: Added deleteTempFile(). + * PeerAbstractCommand.cc: do not stop execution after download + completes. This makes localhost a seeder. + * Util.{h,cc}: Added fileCopy(). + * PeerListenCommand.cc: do not stop execution after download completes. + This makes localhost a seeder. + * main.cc: Do not call TorrentMan::fixFilename() in torrentHandler. + Added TorrentMan::deleteTempFile() to torrentHandler. + Initialized the variable dir as ".". + * TorrentMan.h: Changed DEFAULT_ANNOUNCE_INTERVAL to 120 seconds. + Deleted renameSingleFile(). + Added copySingleFile(), deleteTempFile(). + * DownloadEngine.h: Added virtual function afterEachIteration(). + * TorrentDownloadEngine.cc: Move a call to TorrentMan::fixFilename() + in onEndOfRun() to afterEachIteration(). + In onEndOfRun(), changed if condition to check whether filenameFixed is + true. + * Util.cc: Implemented fileCopy() using rangedFileCopy(). + In rangedFileCopy(), added try-catch block to properly close file + descriptors. + * TorrentDownloadEngine.cc: Added a member variable filenameFixed. + Added afterEachIteration(), isFilenameFixed(). + * Peer.cc: Changed choking strategy. + * PreAllocationDiskWriter.cc: Drop O_DIRECT flag. + * TrackerInitCommand.cc: Send completed event only once. + * DownloadEngine.cc: Added a call to afterEachIteration(). + * TrackerUpdateCommand.cc: Do not stop execution after download + completes. + * TorrentMan.h: Defined MAX_PEER_UPDATE as 15. aria2 attempts to + connect the peers at most MAX_PEER_UPDATE when a peer list is + received from a tracker. + * TrackerUpdateCommand.cc: Implemented above mentioned behavior. + Decreased the number of failure peers to delete to 0(just comment out + the line). + * Release 0.3.1 + 2006-03-23 Tatsuhiro Tsujikawa * PeerInteractionCommand.cc: added a call to @@ -34,7 +80,8 @@ 2006-03-22 Tatsuhiro Tsujikawa * BitTorrent protocol support added. - + * Release 0.3.0 + 2006-03-17 Tatsuhiro Tsujikawa * SocketCore.cc: remove the assignment of addrinfo.ai_addr. diff --git a/README b/README index ae5f7127..8ce02e94 100644 --- a/README +++ b/README @@ -50,6 +50,9 @@ multi-file mode: The directory to store the top directory of downloaded files can be specified by -d option. +In both mode, aria2 needs at least 2 times more disk space than the file size +itself because it creates complete temporary file. + Note: * -o option is used to change the filename of downloaded .torrent file. * This version only supports compact peers list format. diff --git a/configure b/configure index cee2268c..071679a4 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for aria2c 0.3.0. +# Generated by GNU Autoconf 2.59 for aria2c 0.3.1. # # Report bugs to . # @@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='aria2c' PACKAGE_TARNAME='aria2c' -PACKAGE_VERSION='0.3.0' -PACKAGE_STRING='aria2c 0.3.0' +PACKAGE_VERSION='0.3.1' +PACKAGE_STRING='aria2c 0.3.1' PACKAGE_BUGREPORT='tujikawa@rednoah.com' ac_unique_file="src/Socket.h" @@ -788,7 +788,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures aria2c 0.3.0 to adapt to many kinds of systems. +\`configure' configures aria2c 0.3.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -854,7 +854,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of aria2c 0.3.0:";; + short | recursive ) echo "Configuration of aria2c 0.3.1:";; esac cat <<\_ACEOF @@ -989,7 +989,7 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -aria2c configure 0.3.0 +aria2c configure 0.3.1 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. @@ -1003,7 +1003,7 @@ cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by aria2c $as_me 0.3.0, which was +It was created by aria2c $as_me 0.3.1, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1646,7 +1646,7 @@ fi # Define the identity of the package. PACKAGE='aria2c' - VERSION='0.3.0' + VERSION='0.3.1' cat >>confdefs.h <<_ACEOF @@ -10971,7 +10971,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by aria2c $as_me 0.3.0, which was +This file was extended by aria2c $as_me 0.3.1, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11034,7 +11034,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -aria2c config.status 0.3.0 +aria2c config.status 0.3.1 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.in b/configure.in index 2d8a780e..c3588f41 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. # AC_PREREQ(2.59) -AC_INIT(aria2c, 0.3.0, tujikawa@rednoah.com) +AC_INIT(aria2c, 0.3.1, tujikawa@rednoah.com) AM_INIT_AUTOMAKE() AM_PATH_CPPUNIT(1.10.2) AC_CONFIG_SRCDIR([src/Socket.h]) diff --git a/po/Makefile.in b/po/Makefile.in index d1cc459a..2fd3f8e5 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -9,7 +9,7 @@ # General Public License and is *not* in the public domain. PACKAGE = aria2c -VERSION = 0.3.0 +VERSION = 0.3.1 SHELL = /bin/sh diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 42059e0f..1134000f 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -47,6 +47,7 @@ void DownloadEngine::run() { delete(com); } } + afterEachIteration(); shortSleep(); if(!noWait && !commands.empty()) { waitData(); diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h index 10e9dffa..1d65c411 100644 --- a/src/DownloadEngine.h +++ b/src/DownloadEngine.h @@ -51,6 +51,7 @@ protected: virtual void initStatistics() = 0; virtual void calculateStatistics() = 0; virtual void onEndOfRun() = 0; + virtual void afterEachIteration() {} public: bool noWait; Commands commands; diff --git a/src/Peer.cc b/src/Peer.cc index a517720e..fca917d3 100644 --- a/src/Peer.cc +++ b/src/Peer.cc @@ -34,16 +34,16 @@ void Peer::updateBitfield(int index, int operation) { #define THRESHOLD 1024*1024*2 bool Peer::shouldChoke() const { - if(bitfield->countBlock()*0.8 < bitfield->countMissingBlock()) { + if(bitfield->countBlock()*0.7 < bitfield->countMissingBlock()) { return false; } - if(peerDownload < pieceLength*4 && peerUpload < pieceLength*4) { + if(peerDownload <= pieceLength*10) { return false; } if(amChocking) { - return !(peerDownload+pieceLength*4 < peerUpload); + return !(peerDownload+pieceLength*5 < peerUpload); } else { - return peerDownload >= peerUpload+pieceLength*4; + return peerDownload >= peerUpload+pieceLength*5; } } diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc index 9de87869..92f1ac7a 100644 --- a/src/PeerAbstractCommand.cc +++ b/src/PeerAbstractCommand.cc @@ -73,9 +73,6 @@ bool PeerAbstractCommand::isTimeoutDetected() { bool PeerAbstractCommand::execute() { try { - if(e->torrentMan->downloadComplete()) { - return true; - } beforeSocketCheck(); if(checkSocketIsReadable && !readCheckTarget->isReadable(0) || checkSocketIsWritable && !writeCheckTarget->isWritable(0)) { diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 6c6b3ab5..4e2a6969 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -124,6 +124,13 @@ void PeerInteractionCommand::syncPiece() { } void PeerInteractionCommand::decideChoking() { + if(e->torrentMan->downloadComplete()) { + if(peer->amChocking && peer->peerInterested) { + PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection); + pendingMessages.push_back(pendingMessage); + } + return; + } if(peer->shouldChoke()) { if(!peer->amChocking) { PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection); diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc index bf8efe67..af680bac 100644 --- a/src/PeerListenCommand.cc +++ b/src/PeerListenCommand.cc @@ -52,9 +52,6 @@ int PeerListenCommand::bindPort(int portRangeStart, int portRangeEnd) { } bool PeerListenCommand::execute() { - if(e->torrentMan->downloadComplete()) { - return true; - } for(int i = 0; i < 3 && socket->isReadable(0); i++) { Socket* peerSocket = NULL; try { diff --git a/src/PreAllocationDiskWriter.cc b/src/PreAllocationDiskWriter.cc index 9fef82f8..6f528b2e 100644 --- a/src/PreAllocationDiskWriter.cc +++ b/src/PreAllocationDiskWriter.cc @@ -34,35 +34,23 @@ PreAllocationDiskWriter::PreAllocationDiskWriter(long long int totalLength) PreAllocationDiskWriter::~PreAllocationDiskWriter() {} void PreAllocationDiskWriter::initAndOpenFile(string filename) { - createFile(filename, O_DIRECT); + createFile(filename); - int pageSize = getpagesize(); - int bufSize = pageSize*4; - char* buf; - int rt = posix_memalign((void**)&buf, pageSize, bufSize); - if(rt != 0) { - throw new DlAbortEx(strerror(rt)); + int bufSize = 4096; + char buf[4096]; + + memset(buf, 0, bufSize); + long long int x = totalLength/bufSize; + int r = totalLength%bufSize; + for(long long int i = 0; i < x; i++) { + if(write(fd, buf, bufSize) < 0) { + throw new DlAbortEx(strerror(errno)); + } } - try { - memset(buf, 0, bufSize); - long long int x = totalLength/bufSize; - int r = totalLength%bufSize; - for(long long int i = 0; i < x; i++) { - if(write(fd, buf, bufSize) < 0) { + if(r > 0) { + seek(totalLength-r); + if(write(fd, buf, r) < 0) { throw new DlAbortEx(strerror(errno)); - } } - closeFile(); - openExistingFile(filename); - if(r > 0) { - seek(totalLength-r); - if(write(fd, buf, r) < 0) { - throw new DlAbortEx(strerror(errno)); - } - } - free(buf); - } catch(Exception* ex) { - free(buf); - throw; } } diff --git a/src/Request.h b/src/Request.h index 9bd55948..6c019156 100644 --- a/src/Request.h +++ b/src/Request.h @@ -97,7 +97,8 @@ public: AUTO, STARTED, STOPPED, - COMPLETED + COMPLETED, + AFTER_COMPLETED }; }; diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/TorrentConsoleDownloadEngine.cc index 8a793e91..60e487fd 100644 --- a/src/TorrentConsoleDownloadEngine.cc +++ b/src/TorrentConsoleDownloadEngine.cc @@ -27,14 +27,19 @@ TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {} TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {} void TorrentConsoleDownloadEngine::printStatistics() { - printf("\r "); + printf("\r "); printf("\r"); - printf("%s/%sB %d%% DW:%.2f UP:%.2f(%s) %dpeers", - Util::llitos(torrentMan->getDownloadedSize(), true).c_str(), - Util::llitos(torrentMan->totalSize, true).c_str(), - (torrentMan->totalSize == 0 ? - 0 : (int)((torrentMan->getDownloadedSize()*100)/torrentMan->totalSize)), - downloadSpeed/1000.0, + if(torrentMan->downloadComplete()) { + printf("Download Completed "); + } else { + printf("%s/%sB %d%% DW:%.2f", + Util::llitos(torrentMan->getDownloadedSize(), true).c_str(), + Util::llitos(torrentMan->totalSize, true).c_str(), + (torrentMan->totalSize == 0 ? + 0 : (int)((torrentMan->getDownloadedSize()*100)/torrentMan->totalSize)), + downloadSpeed/1000.0); + } + printf(" UP:%.2f(%s) %dpeers", uploadSpeed/1000.0, Util::llitos(torrentMan->getUploadedSize(), true).c_str(), torrentMan->connections); @@ -42,15 +47,8 @@ void TorrentConsoleDownloadEngine::printStatistics() { } void TorrentConsoleDownloadEngine::initStatistics() { - /* - gettimeofday(&cp, NULL); - */ downloadSpeed = 0; uploadSpeed = 0; - /* - sessionDownloadSize = 0; - sessionUploadSize = 0; - */ lastElapsed = 0; gettimeofday(&cp[0], NULL); gettimeofday(&cp[1], NULL); @@ -61,34 +59,12 @@ void TorrentConsoleDownloadEngine::initStatistics() { currentCp = 0; } -/* -int TorrentConsoleDownloadEngine::calculateSpeed(int deltaSize, long long int elapsed, int prevSpeed) { - int nowSpeed = (int)(deltaSize/(elapsed/1000000.0)); - return (nowSpeed+prevSpeed)/2; -} -*/ int TorrentConsoleDownloadEngine::calculateSpeed(long long int sessionSize, long long int elapsed) { int nowSpeed = (int)(sessionSize/(elapsed/1000000.0)); return nowSpeed; } void TorrentConsoleDownloadEngine::calculateStatistics() { - /* - struct timeval now; - gettimeofday(&now, NULL); - long long int elapsed = Util::difftv(now, cp); - sessionDownloadSize += torrentMan->getDeltaDownload(); - sessionUploadSize += torrentMan->getDeltaUpload(); - - downloadSpeed = calculateSpeed(sessionDownloadSize, elapsed); - uploadSpeed = calculateSpeed(sessionUploadSize, elapsed); - torrentMan->resetDeltaDownload(); - torrentMan->resetDeltaUpload(); - if(elapsed-lastElapsed >= 1000000) { - printStatistics(); - lastElapsed = elapsed; - } - */ struct timeval now; gettimeofday(&now, NULL); long long int elapsed = Util::difftv(now, cp[currentCp]); @@ -116,17 +92,4 @@ void TorrentConsoleDownloadEngine::calculateStatistics() { lastElapsed = 0; currentCp = currentCp ? 0 : 1; } - - /* - if(elapsed >= 1000000) { - downloadSpeed = calculateSpeed(torrentMan->getDeltaDownload(), - elapsed, downloadSpeed); - uploadSpeed = calculateSpeed(torrentMan->getDeltaUpload(), - elapsed, uploadSpeed); - torrentMan->resetDeltaDownload(); - torrentMan->resetDeltaUpload(); - cp = now; - printStatistics(); - } - */ } diff --git a/src/TorrentDownloadEngine.cc b/src/TorrentDownloadEngine.cc index 17f2f301..9ab1520a 100644 --- a/src/TorrentDownloadEngine.cc +++ b/src/TorrentDownloadEngine.cc @@ -23,10 +23,19 @@ void TorrentDownloadEngine::onEndOfRun() { torrentMan->diskWriter->closeFile(); - if(torrentMan->downloadComplete()) { + if(filenameFixed && torrentMan->downloadComplete()) { torrentMan->remove(); - torrentMan->fixFilename(); } else { torrentMan->save(); } } + +void TorrentDownloadEngine::afterEachIteration() { + if(!filenameFixed && torrentMan->downloadComplete()) { + torrentMan->diskWriter->closeFile(); + torrentMan->save(); + torrentMan->fixFilename(); + filenameFixed = true; + torrentMan->diskWriter->openExistingFile(torrentMan->getTempFilePath()); + } +} diff --git a/src/TorrentDownloadEngine.h b/src/TorrentDownloadEngine.h index fca3daa5..8bbd7606 100644 --- a/src/TorrentDownloadEngine.h +++ b/src/TorrentDownloadEngine.h @@ -26,13 +26,18 @@ #include "TorrentMan.h" class TorrentDownloadEngine : public DownloadEngine { +private: + bool filenameFixed; protected: void onEndOfRun(); + void afterEachIteration(); public: - TorrentDownloadEngine() {} + TorrentDownloadEngine():filenameFixed(false) {} virtual ~TorrentDownloadEngine() {} TorrentMan* torrentMan; + + bool isFilenameFixed() const { return filenameFixed; } }; #endif // _D_TORRENT_DOWNLOAD_ENGINE_H_ diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc index 8f357bdb..e5b8adbd 100644 --- a/src/TorrentMan.cc +++ b/src/TorrentMan.cc @@ -336,7 +336,6 @@ void TorrentMan::setup(string metaInfoFile) { itr++) { Dictionary* fileDic = (Dictionary*)(*itr); Data* lengthData = (Data*)fileDic->get("length"); - //length += strtoll(data->toString().c_str(), NULL, 10); length += lengthData->toLLInt(); List* path = (List*)fileDic->get("path"); const MetaList& paths = path->getList(); @@ -490,25 +489,30 @@ void TorrentMan::remove() const { void TorrentMan::fixFilename() const { if(fileMode == SINGLE) { - renameSingleFile(); + copySingleFile(); } else { splitMultiFile(); } } -void TorrentMan::renameSingleFile() const { - rename(getTempFilePath().c_str(), getFilePath().c_str()); +void TorrentMan::copySingleFile() const { + logger->info("writing file %s", getFilePath().c_str()); + Util::fileCopy(getFilePath(), getTempFilePath()); } void TorrentMan::splitMultiFile() const { logger->info("creating directories"); multiFileTopDir->createDir(storeDir, true); long long int offset = 0; - logger->info("splitting file"); for(MultiFileEntries::const_iterator itr = multiFileEntries.begin(); itr != multiFileEntries.end(); itr++) { - Util::rangedFileCopy(storeDir+"/"+itr->path, getTempFilePath(), offset, itr->length); + string dest = storeDir+"/"+itr->path; + logger->info("writing file %s", dest.c_str()); + Util::rangedFileCopy(dest, getTempFilePath(), offset, itr->length); offset += itr->length; } +} + +void TorrentMan::deleteTempFile() const { unlink(getTempFilePath().c_str()); } diff --git a/src/TorrentMan.h b/src/TorrentMan.h index 92221293..32df4260 100644 --- a/src/TorrentMan.h +++ b/src/TorrentMan.h @@ -42,9 +42,11 @@ using namespace std; #define IS_NULL_PIECE(X) (X.index == 0 && X.length == 0) -#define DEFAULT_ANNOUNCE_INTERVAL 1800 +#define DEFAULT_ANNOUNCE_INTERVAL 120 #define DEFAULT_ANNOUNCE_MIN_INTERVAL 120 #define MAX_PEERS 55 +#define MAX_PEER_UPDATE 15 + #define MAX_PEER_LIST_SIZE 250 #define END_GAME_PIECE_NUM 20 @@ -203,9 +205,10 @@ public: void save() const; void remove() const; - void renameSingleFile() const; + void copySingleFile() const; void splitMultiFile() const; void fixFilename() const; + void deleteTempFile() const; void setPort(int port) { this->port = port; } int getPort() const { return port; } diff --git a/src/TrackerInitCommand.cc b/src/TrackerInitCommand.cc index eefc636c..5d53ef9c 100644 --- a/src/TrackerInitCommand.cc +++ b/src/TrackerInitCommand.cc @@ -31,7 +31,11 @@ TrackerInitCommand::~TrackerInitCommand() {} bool TrackerInitCommand::execute() { if(e->torrentMan->downloadComplete()) { - req->setTrackerEvent(Request::COMPLETED); + if(req->getTrackerEvent() == Request::COMPLETED) { + req->setTrackerEvent(Request::AFTER_COMPLETED); + } else { + req->setTrackerEvent(Request::COMPLETED); + } } string event; switch(req->getTrackerEvent()) { diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc index 8ef3e0ae..2110e420 100644 --- a/src/TrackerUpdateCommand.cc +++ b/src/TrackerUpdateCommand.cc @@ -40,10 +40,7 @@ TrackerUpdateCommand::~TrackerUpdateCommand() { } bool TrackerUpdateCommand::execute() { - if(req->getTrackerEvent() == Request::COMPLETED) { - return true; - } - e->torrentMan->deleteOldErrorPeers(25); + //e->torrentMan->deleteOldErrorPeers(25); Dictionary* response = (Dictionary*)trackerResponse; Data* failureReason = (Data*)response->get("failure reason"); @@ -110,7 +107,7 @@ bool TrackerUpdateCommand::execute() { } */ while(e->torrentMan->isPeerAvailable() && - e->torrentMan->connections < MAX_PEERS) { + e->torrentMan->connections < MAX_PEER_UPDATE) { Peer* peer = e->torrentMan->getPeer(); int newCuid = e->torrentMan->getNewCuid(); peer->cuid = newCuid; diff --git a/src/Util.cc b/src/Util.cc index bd18037d..5396d60c 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -21,6 +21,7 @@ /* copyright --> */ #include "Util.h" #include "DlAbortEx.h" +#include "File.h" #include #include #include @@ -190,41 +191,58 @@ FILE* Util::openFile(string filename, string mode) { return file; } -void Util::rangedFileCopy(string dest, string src, long long int srcOffset, long long int length) { - int destFd; - if((destFd = open(dest.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) { - throw new DlAbortEx(strerror(errno)); - } - int srcFd; - if((srcFd = open(src.c_str(), O_RDONLY, S_IRUSR|S_IWUSR)) < 0) { - throw new DlAbortEx(strerror(errno)); - } - if(lseek(srcFd, srcOffset, SEEK_SET) != srcOffset) { - throw new DlAbortEx(strerror(errno)); - } - int BUF_SIZE = 16*1024; - char buf[BUF_SIZE]; - int x = length/BUF_SIZE; - int r = length%BUF_SIZE; - for(int i = 0; i < x; i++) { - int readLength; - if((readLength = read(srcFd, buf, BUF_SIZE)) == -1 || readLength != BUF_SIZE) { - throw new DlAbortEx(strerror(errno)); - } - if(write(destFd, buf, readLength) == -1) { - throw new DlAbortEx(strerror(errno)); - } - } - if(r > 0) { - int readLength; - if((readLength = read(srcFd, buf, r)) == -1 || readLength != r) { - throw new DlAbortEx(strerror(errno)); - } - if(write(destFd, buf, readLength) == -1) { - throw new DlAbortEx(strerror(errno)); - } - } - close(srcFd); - close(destFd); +void Util::fileCopy(string dest, string src) { + File file(src); + rangedFileCopy(dest, src, 0, file.size()); +} + +void Util::rangedFileCopy(string dest, string src, long long int srcOffset, long long int length) { + int bufSize = 4096; + char buf[bufSize]; + int destFd = -1; + int srcFd = -1; + try { + if((destFd = open(dest.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) { + throw new DlAbortEx(strerror(errno)); + } + if((srcFd = open(src.c_str(), O_RDONLY, S_IRUSR|S_IWUSR)) == -1) { + throw new DlAbortEx(strerror(errno)); + } + if(lseek(srcFd, srcOffset, SEEK_SET) != srcOffset) { + throw new DlAbortEx(strerror(errno)); + } + int x = length/bufSize; + int r = length%bufSize; + for(int i = 0; i < x; i++) { + int readLength; + if((readLength = read(srcFd, buf, bufSize)) == -1 || readLength != bufSize) { + throw new DlAbortEx(strerror(errno)); + } + if(write(destFd, buf, readLength) == -1) { + throw new DlAbortEx(strerror(errno)); + } + } + if(r > 0) { + int readLength; + if((readLength = read(srcFd, buf, r)) == -1 || readLength != r) { + throw new DlAbortEx(strerror(errno)); + } + if(write(destFd, buf, r) == -1) { + throw new DlAbortEx(strerror(errno)); + } + } + close(srcFd); + close(destFd); + srcFd = -1; + destFd = -1; + } catch(Exception* e) { + if(srcFd != -1) { + close(srcFd); + } + if(destFd != -1) { + close(destFd); + } + throw; + } } diff --git a/src/Util.h b/src/Util.h index b3244df6..6b96b6a1 100644 --- a/src/Util.h +++ b/src/Util.h @@ -63,6 +63,8 @@ public: static FILE* openFile(string filename, string mode); + static void fileCopy(string destFile, string src); + static void rangedFileCopy(string destFile, string src, long long int srcOffset, long long int length); }; diff --git a/src/main.cc b/src/main.cc index 7fd0d4a6..00b9b541 100644 --- a/src/main.cc +++ b/src/main.cc @@ -85,9 +85,9 @@ void torrentHandler(int signal) { if(te->torrentMan->diskWriter != NULL) { te->torrentMan->diskWriter->closeFile(); } - if(te->torrentMan->downloadComplete()) { + if(te->torrentMan->downloadComplete() && te->isFilenameFixed()) { te->torrentMan->remove(); - te->torrentMan->fixFilename(); + te->torrentMan->deleteTempFile(); printDownloadCompeleteMessage(te->torrentMan->getFilePath()); } else { te->torrentMan->save(); @@ -223,7 +223,7 @@ int main(int argc, char* argv[]) { #endif // ENABLE_NLS bool stdoutLog = false; string logfile; - string dir; + string dir = "."; string ufilename; int split = 1; bool daemonMode = false; @@ -575,7 +575,7 @@ int main(int argc, char* argv[]) { new PeerListenCommand(te->torrentMan->getNewCuid(), te); int port = listenCommand->bindPort(6881, 6999); if(port == -1) { - printf("an error occurred while binding port.\n"); + printf("Errors occurred while binding port.\n"); exit(1); } te->torrentMan->setPort(port);