mirror of https://github.com/aria2/aria2
2007-11-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Now a file is stored in the directory specified in .metalnk file (file[@name]). * src/Metalink2RequestGroup.cc Create the directory structure when opening the file if it doesn't exist. * src/AbstractDiskWriter.cc * src/Util.{h, cc} * src/File.h * test/UtilTest.cc Removed file name comparison * src/Metalink2RequestGroup.cc * src/HttpResponseCommand.cc Rewritten using Util::mkdirs() * src/FileEntry.cc (setupDir) * test/FileEntryTest.cc Updated doc * src/SingleFileDownloadContext.hpull/1/head
parent
bcbadb3b6b
commit
52b43151c6
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
||||||
|
2007-11-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Now a file is stored in the directory specified in .metalnk file
|
||||||
|
(file[@name]).
|
||||||
|
* src/Metalink2RequestGroup.cc
|
||||||
|
|
||||||
|
Create the directory structure when opening the file if it doesn't
|
||||||
|
exist.
|
||||||
|
* src/AbstractDiskWriter.cc
|
||||||
|
* src/Util.{h, cc}
|
||||||
|
* src/File.h
|
||||||
|
* test/UtilTest.cc
|
||||||
|
|
||||||
|
Removed file name comparison
|
||||||
|
* src/Metalink2RequestGroup.cc
|
||||||
|
* src/HttpResponseCommand.cc
|
||||||
|
|
||||||
|
Rewritten using Util::mkdirs()
|
||||||
|
* src/FileEntry.cc (setupDir)
|
||||||
|
* test/FileEntryTest.cc
|
||||||
|
|
||||||
|
Updated doc
|
||||||
|
* src/SingleFileDownloadContext.h
|
||||||
|
|
||||||
2007-11-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2007-11-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Now SleepCommand dispatches nextCommand when halt is requested.
|
Now SleepCommand dispatches nextCommand when halt is requested.
|
||||||
|
|
2
TODO
2
TODO
|
@ -53,4 +53,4 @@
|
||||||
* Implement duplicate download checking in Bt
|
* Implement duplicate download checking in Bt
|
||||||
* improve --metalink-location field
|
* improve --metalink-location field
|
||||||
* Use content-type for PostDownloadHandler
|
* Use content-type for PostDownloadHandler
|
||||||
* Fix SleepCommand to catch halt signal
|
|
||||||
|
|
|
@ -92,11 +92,8 @@ void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags)
|
||||||
throw(DlAbortEx*)
|
throw(DlAbortEx*)
|
||||||
{
|
{
|
||||||
this->filename = filename;
|
this->filename = filename;
|
||||||
// TODO proper filename handling needed
|
|
||||||
assert(filename.size());
|
assert(filename.size());
|
||||||
// if(filename.empty()) {
|
Util::mkdirs(File(filename).getDirname());
|
||||||
// filename = "index.html";
|
|
||||||
// }
|
|
||||||
if((fd = open(filename.c_str(), O_CREAT|O_RDWR|O_TRUNC|O_BINARY|addFlags, OPEN_MODE)) < 0) {
|
if((fd = open(filename.c_str(), O_CREAT|O_RDWR|O_TRUNC|O_BINARY|addFlags, OPEN_MODE)) < 0) {
|
||||||
throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
|
throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,11 @@ public:
|
||||||
|
|
||||||
string getDirname() const;
|
string getDirname() const;
|
||||||
|
|
||||||
|
const string& getPath() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
static bool isDir(const string& filename);
|
static bool isDir(const string& filename);
|
||||||
|
|
||||||
bool renameTo(const string& dest);
|
bool renameTo(const string& dest);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "FileEntry.h"
|
#include "FileEntry.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "DlAbortEx.h"
|
#include "Util.h"
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
FileEntry::FileEntry(const string& path,
|
FileEntry::FileEntry(const string& path,
|
||||||
|
@ -48,21 +48,7 @@ FileEntry::~FileEntry() {}
|
||||||
|
|
||||||
void FileEntry::setupDir(const string& parentDir)
|
void FileEntry::setupDir(const string& parentDir)
|
||||||
{
|
{
|
||||||
string absPath = parentDir+"/"+path;
|
Util::mkdirs(File(parentDir+"/"+path).getDirname());
|
||||||
char* temp = strdup(absPath.c_str());
|
|
||||||
string dir = string(dirname(temp));
|
|
||||||
free(temp);
|
|
||||||
if(!dir.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
File f(dir);
|
|
||||||
if(f.isDir()) {
|
|
||||||
// nothing to do
|
|
||||||
} else if(f.exists()) {
|
|
||||||
throw new DlAbortEx("%s is not a directory.", dir.c_str());
|
|
||||||
} else if(!f.mkdirs()) {
|
|
||||||
throw new DlAbortEx("Failed to create directory %s.", dir.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileEntry& FileEntry::operator=(const FileEntry& entry)
|
FileEntry& FileEntry::operator=(const FileEntry& entry)
|
||||||
|
|
|
@ -91,14 +91,12 @@ bool HttpResponseCommand::executeInternal()
|
||||||
}
|
}
|
||||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||||
// validate totalsize
|
// validate totalsize
|
||||||
_requestGroup->validateFilename(httpResponse->determinFilename());
|
|
||||||
_requestGroup->validateTotalLength(httpResponse->getEntityLength());
|
_requestGroup->validateTotalLength(httpResponse->getEntityLength());
|
||||||
|
|
||||||
e->commands.push_back(createHttpDownloadCommand(httpResponse));
|
e->commands.push_back(createHttpDownloadCommand(httpResponse));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// validate totalsize against hintTotalSize if it is provided.
|
// validate totalsize against hintTotalSize if it is provided.
|
||||||
_requestGroup->validateFilenameByHint(httpResponse->determinFilename());
|
|
||||||
_requestGroup->validateTotalLengthByHint(httpResponse->getEntityLength());
|
_requestGroup->validateTotalLengthByHint(httpResponse->getEntityLength());
|
||||||
|
|
||||||
SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(httpResponse->determinFilename());
|
SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(httpResponse->determinFilename());
|
||||||
|
|
|
@ -159,7 +159,8 @@ RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile)
|
||||||
SingleFileDownloadContextHandle dctx =
|
SingleFileDownloadContextHandle dctx =
|
||||||
new SingleFileDownloadContext(pieceLength,
|
new SingleFileDownloadContext(pieceLength,
|
||||||
0,
|
0,
|
||||||
"");
|
"",
|
||||||
|
entry->file->getPath());
|
||||||
dctx->setDir(_option->get(PREF_DIR));
|
dctx->setDir(_option->get(PREF_DIR));
|
||||||
if(!entry->chunkChecksum.isNull()) {
|
if(!entry->chunkChecksum.isNull()) {
|
||||||
dctx->setPieceHashes(entry->chunkChecksum->getChecksums());
|
dctx->setPieceHashes(entry->chunkChecksum->getChecksums());
|
||||||
|
@ -169,7 +170,6 @@ RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile)
|
||||||
// * hash and hash algorithm
|
// * hash and hash algorithm
|
||||||
|
|
||||||
rg->setDownloadContext(dctx);
|
rg->setDownloadContext(dctx);
|
||||||
rg->setHintFilename(entry->file->getBasename());
|
|
||||||
rg->setHintTotalLength(entry->getLength());
|
rg->setHintTotalLength(entry->getLength());
|
||||||
rg->setNumConcurrentCommand(entry->maxConnections < 0 ?
|
rg->setNumConcurrentCommand(entry->maxConnections < 0 ?
|
||||||
_option->getAsInt(PREF_METALINK_SERVERS) :
|
_option->getAsInt(PREF_METALINK_SERVERS) :
|
||||||
|
|
|
@ -46,6 +46,10 @@ private:
|
||||||
* If _ufilename is not zero-length string, then _dir + _ufilename.
|
* If _ufilename is not zero-length string, then _dir + _ufilename.
|
||||||
*/
|
*/
|
||||||
FileEntryHandle _fileEntry;
|
FileEntryHandle _fileEntry;
|
||||||
|
/**
|
||||||
|
* _filename and _ufilename may contains directory path name.
|
||||||
|
* So usr/local/aria2c is acceptable here.
|
||||||
|
*/
|
||||||
string _filename;
|
string _filename;
|
||||||
string _ufilename;
|
string _ufilename;
|
||||||
|
|
||||||
|
|
11
src/Util.cc
11
src/Util.cc
|
@ -763,3 +763,14 @@ int32_t Util::alphaToNum(const string& alphabets)
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Util::mkdirs(const string& dirpath)
|
||||||
|
{
|
||||||
|
File dir(dirpath);
|
||||||
|
if(dir.isDir()) {
|
||||||
|
// do nothing
|
||||||
|
} else if(dir.exists()) {
|
||||||
|
throw new DlAbortEx(EX_MAKE_DIR, dir.getPath().c_str(), "File already exists.");
|
||||||
|
} else if(!dir.mkdirs()) {
|
||||||
|
throw new DlAbortEx(EX_MAKE_DIR, dir.getPath().c_str(), strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -150,6 +150,8 @@ public:
|
||||||
static bool isUppercase(const string& what);
|
static bool isUppercase(const string& what);
|
||||||
|
|
||||||
static int32_t alphaToNum(const string& alphabets);
|
static int32_t alphaToNum(const string& alphabets);
|
||||||
|
|
||||||
|
static void mkdirs(const string& dirpath);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _D_UTIL_H_
|
#endif // _D_UTIL_H_
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "FileEntry.h"
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
class FileEntryTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE(FileEntryTest);
|
||||||
|
CPPUNIT_TEST(testSetupDir);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
public:
|
||||||
|
void setUp() {}
|
||||||
|
|
||||||
|
void testSetupDir();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION( FileEntryTest );
|
||||||
|
|
||||||
|
void FileEntryTest::testSetupDir()
|
||||||
|
{
|
||||||
|
string topDir = "/tmp";
|
||||||
|
string dir = "aria2-FileEntryTest-testSetupDir";
|
||||||
|
string filename = "filename";
|
||||||
|
string path = topDir+"/"+dir+"/"+filename;
|
||||||
|
File d(topDir+"/"+dir);
|
||||||
|
if(d.exists()) {
|
||||||
|
CPPUNIT_ASSERT(d.remove());
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(!d.exists());
|
||||||
|
FileEntry fileEntry(dir+"/"+filename, 0, 0);
|
||||||
|
fileEntry.setupDir(topDir);
|
||||||
|
CPPUNIT_ASSERT(d.isDir());
|
||||||
|
File f(path);
|
||||||
|
CPPUNIT_ASSERT(!f.exists());
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
TESTS = aria2c
|
TESTS = aria2c
|
||||||
check_PROGRAMS = $(TESTS)
|
check_PROGRAMS = $(TESTS)
|
||||||
aria2c_SOURCES = AllTest.cc\
|
aria2c_SOURCES = AllTest.cc\
|
||||||
|
FileEntryTest.cc\
|
||||||
PieceTest.cc\
|
PieceTest.cc\
|
||||||
DefaultPieceStorageTest.cc\
|
DefaultPieceStorageTest.cc\
|
||||||
SegmentTest.cc\
|
SegmentTest.cc\
|
||||||
|
|
|
@ -112,7 +112,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
am__EXEEXT_1 = aria2c$(EXEEXT)
|
am__EXEEXT_1 = aria2c$(EXEEXT)
|
||||||
am__aria2c_SOURCES_DIST = AllTest.cc PieceTest.cc \
|
am__aria2c_SOURCES_DIST = AllTest.cc FileEntryTest.cc PieceTest.cc \
|
||||||
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||||
SingleFileAllocationIteratorTest.cc \
|
SingleFileAllocationIteratorTest.cc \
|
||||||
DefaultBtProgressInfoFileTest.cc \
|
DefaultBtProgressInfoFileTest.cc \
|
||||||
|
@ -203,9 +203,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc PieceTest.cc \
|
||||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT)
|
@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT)
|
||||||
am_aria2c_OBJECTS = AllTest.$(OBJEXT) PieceTest.$(OBJEXT) \
|
am_aria2c_OBJECTS = AllTest.$(OBJEXT) FileEntryTest.$(OBJEXT) \
|
||||||
DefaultPieceStorageTest.$(OBJEXT) SegmentTest.$(OBJEXT) \
|
PieceTest.$(OBJEXT) DefaultPieceStorageTest.$(OBJEXT) \
|
||||||
GrowSegmentTest.$(OBJEXT) \
|
SegmentTest.$(OBJEXT) GrowSegmentTest.$(OBJEXT) \
|
||||||
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
||||||
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
||||||
SingleFileDownloadContextTest.$(OBJEXT) \
|
SingleFileDownloadContextTest.$(OBJEXT) \
|
||||||
|
@ -414,8 +414,8 @@ target_cpu = @target_cpu@
|
||||||
target_os = @target_os@
|
target_os = @target_os@
|
||||||
target_vendor = @target_vendor@
|
target_vendor = @target_vendor@
|
||||||
TESTS = aria2c
|
TESTS = aria2c
|
||||||
aria2c_SOURCES = AllTest.cc PieceTest.cc DefaultPieceStorageTest.cc \
|
aria2c_SOURCES = AllTest.cc FileEntryTest.cc PieceTest.cc \
|
||||||
SegmentTest.cc GrowSegmentTest.cc \
|
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||||
SingleFileAllocationIteratorTest.cc \
|
SingleFileAllocationIteratorTest.cc \
|
||||||
DefaultBtProgressInfoFileTest.cc \
|
DefaultBtProgressInfoFileTest.cc \
|
||||||
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
||||||
|
@ -540,6 +540,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorageTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorageTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DictionaryTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DictionaryTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfigTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfigTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntryTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileUriListParserTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileUriListParserTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegmentTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegmentTest.Po@am__quote@
|
||||||
|
|
|
@ -28,6 +28,7 @@ class UtilTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testIsLowercase);
|
CPPUNIT_TEST(testIsLowercase);
|
||||||
CPPUNIT_TEST(testIsUppercase);
|
CPPUNIT_TEST(testIsUppercase);
|
||||||
CPPUNIT_TEST(testAlphaToNum);
|
CPPUNIT_TEST(testAlphaToNum);
|
||||||
|
CPPUNIT_TEST(testMkdirs);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ public:
|
||||||
void testIsLowercase();
|
void testIsLowercase();
|
||||||
void testIsUppercase();
|
void testIsUppercase();
|
||||||
void testAlphaToNum();
|
void testAlphaToNum();
|
||||||
|
void testMkdirs();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -364,3 +366,26 @@ void UtilTest::testAlphaToNum()
|
||||||
CPPUNIT_ASSERT_EQUAL((int32_t)675, Util::alphaToNum("ZZ")); // 25*26+25
|
CPPUNIT_ASSERT_EQUAL((int32_t)675, Util::alphaToNum("ZZ")); // 25*26+25
|
||||||
CPPUNIT_ASSERT_EQUAL((int32_t)0, Util::alphaToNum(""));
|
CPPUNIT_ASSERT_EQUAL((int32_t)0, Util::alphaToNum(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UtilTest::testMkdirs()
|
||||||
|
{
|
||||||
|
string dir = "/tmp/aria2-UtilTest-testMkdirs";
|
||||||
|
File d(dir);
|
||||||
|
if(d.exists()) {
|
||||||
|
CPPUNIT_ASSERT(d.remove());
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(!d.exists());
|
||||||
|
Util::mkdirs(dir);
|
||||||
|
CPPUNIT_ASSERT(d.isDir());
|
||||||
|
|
||||||
|
string file = "./UtilTest.cc";
|
||||||
|
File f(file);
|
||||||
|
CPPUNIT_ASSERT(f.isFile());
|
||||||
|
try {
|
||||||
|
Util::mkdirs(file);
|
||||||
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
|
} catch(DlAbortEx* ex) {
|
||||||
|
cerr << ex->getMsg() << endl;
|
||||||
|
delete ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue