// so while the current implementation satisfies the testcases it is not a real option
// to disable it for now
#define APT_USE_ZLIB 1
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
#include <zlib.h>
+#else
+#warning "Usage of zlib is DISABLED!"
#endif
#ifdef WORDS_BIGENDIAN
class FileFdPrivate {
public:
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
gzFile gz;
#else
void* gz;
pid_t compressor_pid;
bool pipe;
APT::Configuration::Compressor compressor;
- FileFd::OpenMode openmode;
+ unsigned int openmode;
FileFdPrivate() : gz(NULL), compressor_pid(-1), pipe(false) {};
};
for (int J = 0; J != 2; J++)
SetCloseExec(Pipe[J],true);
+ int FileFd = -1;
if (Comp == true)
+ {
OutFd = Pipe[1];
+ // FIXME: we should handle openmode and permission from Open() here
+ FileFd = open(FileName.c_str(), O_WRONLY, 0666);
+ }
else
OutFd = Pipe[0];
if (Comp == true)
{
dup2(Pipe[0],STDIN_FILENO);
+ dup2(FileFd,STDOUT_FILENO);
SetCloseExec(STDIN_FILENO,false);
}
else
{
dup2(Pipe[1],STDOUT_FILENO);
- SetCloseExec(STDOUT_FILENO,false);
}
+ SetCloseExec(STDOUT_FILENO,false);
std::vector<char const*> Args;
Args.push_back(Prog.Binary.c_str());
for (std::vector<std::string>::const_iterator a = addArgs->begin();
a != addArgs->end(); ++a)
Args.push_back(a->c_str());
- Args.push_back("--stdout");
- Args.push_back(FileName.c_str());
+ if (Comp == false)
+ {
+ Args.push_back("--stdout");
+ Args.push_back(FileName.c_str());
+ }
Args.push_back(NULL);
execvp(Args[0],(char **)&Args[0]);
_exit(100);
}
if (Comp == true)
+ {
close(Pipe[0]);
+ close(FileFd);
+ }
else
close(Pipe[1]);
// FileFd::Open - Open a file /*{{{*/
// ---------------------------------------------------------------------
/* The most commonly used open mode combinations are given with Mode */
-bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned long const Perms)
+bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const Perms)
{
if (Mode == ReadOnlyGzip)
return Open(FileName, ReadOnly, Gzip, Perms);
- Close();
- d = new FileFdPrivate;
- d->openmode = Mode;
- Flags = AutoClose;
if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
- if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
- return _error->Error("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str());
-
- int fileflags = 0;
-#define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE
- if_FLAGGED_SET(ReadWrite, O_RDWR);
- else if_FLAGGED_SET(ReadOnly, O_RDONLY);
- else if_FLAGGED_SET(WriteOnly, O_WRONLY);
- else return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str());
-
- if_FLAGGED_SET(Create, O_CREAT);
- if_FLAGGED_SET(Exclusive, O_EXCL);
- else if_FLAGGED_SET(Atomic, O_EXCL);
- if_FLAGGED_SET(Empty, O_TRUNC);
-#undef if_FLAGGED_SET
// FIXME: Denote inbuilt compressors somehow - as we don't need to have the binaries for them
std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
if (Compress == Auto)
{
- Compress = None;
for (; compressor != compressors.end(); ++compressor)
{
std::string file = std::string(FileName).append(compressor->Extension);
if (FileExists(file) == false)
continue;
FileName = file;
- if (compressor->Binary == ".")
- Compress = None;
- else
- Compress = Extension;
break;
}
}
else if (Compress == Extension)
{
- Compress = None;
- std::string ext = flExtension(FileName);
- if (ext != FileName)
+ std::string::size_type const found = FileName.find_last_of('.');
+ std::string ext;
+ if (found != std::string::npos)
{
- ext = "." + ext;
- for (; compressor != compressors.end(); ++compressor)
- if (ext == compressor->Extension)
- break;
+ ext = FileName.substr(found);
+ if (ext == ".new" || ext == ".bak")
+ {
+ std::string::size_type const found2 = FileName.find_last_of('.', found - 1);
+ if (found2 != std::string::npos)
+ ext = FileName.substr(found2, found - found2);
+ else
+ ext.clear();
+ }
}
+ for (; compressor != compressors.end(); ++compressor)
+ if (ext == compressor->Extension)
+ break;
+ // no matching extension - assume uncompressed (imagine files like 'example.org_Packages')
+ if (compressor == compressors.end())
+ for (compressor = compressors.begin(); compressor != compressors.end(); ++compressor)
+ if (compressor->Name == ".")
+ break;
}
- else if (Compress != None)
+ else
{
std::string name;
switch (Compress)
{
+ case None: name = "."; break;
case Gzip: name = "gzip"; break;
case Bzip2: name = "bzip2"; break;
case Lzma: name = "lzma"; break;
case Xz: name = "xz"; break;
- default: return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
+ case Auto:
+ case Extension:
+ // Unreachable
+ return _error->Error("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str());
}
for (; compressor != compressors.end(); ++compressor)
if (compressor->Name == name)
break;
- if (compressor == compressors.end() && name != "gzip")
+ if (compressor == compressors.end())
return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
}
- // if we have them, use inbuilt compressors instead of forking
- if (compressor != compressors.end())
- {
-#ifdef APT_USE_ZLIB
- if (compressor->Name == "gzip")
- {
- Compress = Gzip;
- compressor = compressors.end();
- }
- else
-#endif
- if (compressor->Name == ".")
- {
- Compress = None;
- compressor = compressors.end();
- }
- }
+ if (compressor == compressors.end())
+ return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
+ return Open(FileName, Mode, *compressor, Perms);
+}
+bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
+{
+ Close();
+ d = new FileFdPrivate;
+ d->openmode = Mode;
+ Flags = AutoClose;
+
+ if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
+ return _error->Error("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str());
+ if ((Mode & ReadWrite) == 0)
+ return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str());
if ((Mode & Atomic) == Atomic)
{
unlink(FileName.c_str());
}
- if (compressor != compressors.end())
+ // if we have them, use inbuilt compressors instead of forking
+ if (compressor.Name != "."
+#if APT_USE_ZLIB
+ && compressor.Name != "gzip"
+#endif
+ )
{
if ((Mode & ReadWrite) == ReadWrite)
- return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor->Name.c_str(), FileName.c_str());
+ return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor.Name.c_str(), FileName.c_str());
- if (ExecCompressor(*compressor, NULL /*d->compressor_pid*/, FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false)
- return _error->Error("Forking external compressor %s is not implemented for %s", compressor->Name.c_str(), FileName.c_str());
+ if ((Mode & (WriteOnly | Create)) == (WriteOnly | Create))
+ {
+ if (TemporaryFileName.empty() == false)
+ {
+ if (RealFileExists(TemporaryFileName) == false)
+ {
+ iFd = open(TemporaryFileName.c_str(), O_WRONLY | O_CREAT, Perms);
+ close(iFd);
+ iFd = -1;
+ }
+ }
+ else if (RealFileExists(FileName) == false)
+ {
+ iFd = open(FileName.c_str(), O_WRONLY | O_CREAT, Perms);
+ close(iFd);
+ iFd = -1;
+ }
+ }
+
+ if (TemporaryFileName.empty() == false)
+ {
+ if (ExecCompressor(compressor, &(d->compressor_pid), TemporaryFileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false)
+ return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), TemporaryFileName.c_str());
+ }
+ else
+ {
+ if (ExecCompressor(compressor, &(d->compressor_pid), FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false)
+ return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), FileName.c_str());
+ }
d->pipe = true;
- d->compressor = *compressor;
+ d->compressor = compressor;
}
else
{
+ int fileflags = 0;
+ #define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE
+ if_FLAGGED_SET(ReadWrite, O_RDWR);
+ else if_FLAGGED_SET(ReadOnly, O_RDONLY);
+ else if_FLAGGED_SET(WriteOnly, O_WRONLY);
+
+ if_FLAGGED_SET(Create, O_CREAT);
+ if_FLAGGED_SET(Exclusive, O_EXCL);
+ else if_FLAGGED_SET(Atomic, O_EXCL);
+ if_FLAGGED_SET(Empty, O_TRUNC);
+ #undef if_FLAGGED_SET
+
if (TemporaryFileName.empty() == false)
iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
else
if (iFd != -1)
{
- if (OpenInternDescriptor(Mode, Compress) == false)
+ if (OpenInternDescriptor(Mode, compressor) == false)
{
close (iFd);
iFd = -1;
// FileFd::OpenDescriptor - Open a filedescriptor /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose)
+bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose)
+{
+ std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
+ std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
+ std::string name;
+ switch (Compress)
+ {
+ case None: name = "."; break;
+ case Gzip: name = "gzip"; break;
+ case Bzip2: name = "bzip2"; break;
+ case Lzma: name = "lzma"; break;
+ case Xz: name = "xz"; break;
+ case Auto:
+ case Extension:
+ return _error->Error("Opening Fd %d in Auto or Extension compression mode is not supported", Fd);
+ }
+ for (; compressor != compressors.end(); ++compressor)
+ if (compressor->Name == name)
+ break;
+ if (compressor == compressors.end())
+ return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+
+ return OpenDescriptor(Fd, Mode, *compressor, AutoClose);
+}
+bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
{
Close();
d = new FileFdPrivate;
d->openmode = Mode;
Flags = (AutoClose) ? FileFd::AutoClose : 0;
iFd = Fd;
- if (OpenInternDescriptor(Mode, Compress) == false)
+ if (OpenInternDescriptor(Mode, compressor) == false)
{
if (AutoClose)
close (iFd);
this->FileName = "";
return true;
}
-bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress)
+bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
{
- if (Compress == None)
+ if (compressor.Name == ".")
return true;
-#ifdef APT_USE_ZLIB
- else if (Compress == Gzip)
+#if APT_USE_ZLIB
+ else if (compressor.Name == "gzip")
{
if ((Mode & ReadWrite) == ReadWrite)
d->gz = gzdopen(iFd, "r+");
}
#endif
else
- {
- std::string name;
- switch (Compress)
- {
- case Gzip: name = "gzip"; break;
- case Bzip2: name = "bzip2"; break;
- case Lzma: name = "lzma"; break;
- case Xz: name = "xz"; break;
- default: return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
- }
- std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
- std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
- for (; compressor != compressors.end(); ++compressor)
- if (compressor->Name == name)
- break;
- if (compressor == compressors.end() ||
- ExecCompressor(*compressor, NULL /*&(d->compressor_pid)*/,
- FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false)
- return _error->Error("Forking external compressor %s is not implemented for %s", name.c_str(), FileName.c_str());
- d->pipe = true;
- }
+ return _error->Error("Can't find a match for specified compressor %s for file %s", compressor.Name.c_str(), FileName.c_str());
return true;
}
/*}}}*/
*((char *)To) = '\0';
do
{
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz != NULL)
Res = gzread(d->gz,To,Size);
else
char* FileFd::ReadLine(char *To, unsigned long long const Size)
{
*To = '\0';
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz != NULL)
return gzgets(d->gz, To, Size);
#endif
errno = 0;
do
{
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz != NULL)
Res = gzwrite(d->gz,From,Size);
else
return result;
}
int res;
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz)
res = gzseek(d->gz,To,SEEK_SET);
else
bool FileFd::Skip(unsigned long long Over)
{
int res;
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz != NULL)
res = gzseek(d->gz,Over,SEEK_CUR);
else
unsigned long long FileFd::Tell()
{
off_t Res;
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d->gz != NULL)
Res = gztell(d->gz);
else
} while(read != 0);
Seek(0);
}
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
// only check gzsize if we are actually a gzip file, just checking for
// "gz" is not sufficient as uncompressed files could be opened with
// gzopen in "direct" mode as well
bool Res = true;
if ((Flags & AutoClose) == AutoClose)
{
-#ifdef APT_USE_ZLIB
+#if APT_USE_ZLIB
if (d != NULL && d->gz != NULL) {
int const e = gzclose(d->gz);
// gzdopen() on empty files always fails with "buffer error" here, ignore that
if (d != NULL)
{
-// if (d->compressor_pid != -1)
-// ExecWait(d->compressor_pid, "FileFdCompressor", true);
+ if (d->compressor_pid != -1)
+ ExecWait(d->compressor_pid, "FileFdCompressor", true);
delete d;
d = NULL;
}