summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2011-12-19 14:07:51 +0100
committerMichael Vogt <michael.vogt@ubuntu.com>2011-12-19 14:07:51 +0100
commit27da8141d21cfbfc29675510737ee05bdfd4a2b1 (patch)
tree008e311e4c24dbfce3f47643d962cfa67a333a68 /apt-pkg/contrib
parent386566e36bedb453eb6f914e8e14fd555a2bf111 (diff)
parent6fd947bd48449652edf783cfb1362391e63f9be1 (diff)
merged from lp:~donkult/apt/experimental
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/cdromutl.h4
-rw-r--r--apt-pkg/contrib/cmndline.h4
-rw-r--r--apt-pkg/contrib/configuration.h4
-rw-r--r--apt-pkg/contrib/fileutl.cc506
-rw-r--r--apt-pkg/contrib/fileutl.h71
-rw-r--r--apt-pkg/contrib/hashes.h6
-rw-r--r--apt-pkg/contrib/hashsum_template.h5
-rw-r--r--apt-pkg/contrib/md5.h5
-rw-r--r--apt-pkg/contrib/mmap.cc22
-rw-r--r--apt-pkg/contrib/mmap.h5
-rw-r--r--apt-pkg/contrib/netrc.h4
-rw-r--r--apt-pkg/contrib/progress.h4
-rw-r--r--apt-pkg/contrib/sha1.h5
-rw-r--r--apt-pkg/contrib/strutl.h6
14 files changed, 563 insertions, 88 deletions
diff --git a/apt-pkg/contrib/cdromutl.h b/apt-pkg/contrib/cdromutl.h
index 2c6afac0f..e94045b5c 100644
--- a/apt-pkg/contrib/cdromutl.h
+++ b/apt-pkg/contrib/cdromutl.h
@@ -12,6 +12,10 @@
#include <string>
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
// mount cdrom, DeviceName (e.g. /dev/sr0) is optional
bool MountCdrom(std::string Path, std::string DeviceName="");
bool UnmountCdrom(std::string Path);
diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h
index b201d9855..9f505fd41 100644
--- a/apt-pkg/contrib/cmndline.h
+++ b/apt-pkg/contrib/cmndline.h
@@ -44,6 +44,10 @@
#ifndef PKGLIB_CMNDLINE_H
#define PKGLIB_CMNDLINE_H
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/configuration.h>
+#endif
+
class Configuration;
class CommandLine
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index f6f2a3c1d..4c2e75041 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -34,6 +34,10 @@
#include <vector>
#include <iostream>
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
class Configuration
{
public:
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 95058cbde..a98c2cb85 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -24,6 +24,7 @@
#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/configuration.h>
#include <cstdlib>
@@ -43,6 +44,16 @@
#include <set>
#include <algorithm>
+// FIXME: Compressor Fds have some speed disadvantages and are a bit buggy currently,
+// so while the current implementation satisfies the testcases it is not a real option
+// to disable it for now
+#define APT_USE_ZLIB 1
+#if APT_USE_ZLIB
+#include <zlib.h>
+#else
+#pragma message "Usage of zlib is DISABLED!"
+#endif
+
#ifdef WORDS_BIGENDIAN
#include <inttypes.h>
#endif
@@ -52,6 +63,21 @@
using namespace std;
+class FileFdPrivate {
+ public:
+#if APT_USE_ZLIB
+ gzFile gz;
+#else
+ void* gz;
+#endif
+ int compressed_fd;
+ pid_t compressor_pid;
+ bool pipe;
+ APT::Configuration::Compressor compressor;
+ unsigned int openmode;
+ FileFdPrivate() : gz(NULL), compressed_fd(-1), compressor_pid(-1), pipe(false) {};
+};
+
// RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -718,85 +744,288 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
// FileFd::Open - Open a file /*{{{*/
// ---------------------------------------------------------------------
/* The most commonly used open mode combinations are given with Mode */
-bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms)
+bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const Perms)
{
- Close();
- Flags = AutoClose;
- switch (Mode)
+ if (Mode == ReadOnlyGzip)
+ return Open(FileName, ReadOnly, Gzip, Perms);
+
+ if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
+ return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
+
+ // 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)
{
- case ReadOnly:
- iFd = open(FileName.c_str(),O_RDONLY);
- break;
-
- case ReadOnlyGzip:
- iFd = open(FileName.c_str(),O_RDONLY);
- if (iFd > 0) {
- gz = gzdopen (iFd, "r");
- if (gz == NULL) {
- close (iFd);
- iFd = -1;
- }
- }
- break;
-
- case WriteAtomic:
+ for (; compressor != compressors.end(); ++compressor)
{
- Flags |= Replace;
- char *name = strdup((FileName + ".XXXXXX").c_str());
- TemporaryFileName = string(mktemp(name));
- iFd = open(TemporaryFileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
- free(name);
+ std::string file = std::string(FileName).append(compressor->Extension);
+ if (FileExists(file) == false)
+ continue;
+ FileName = file;
break;
}
-
- case WriteEmpty:
+ }
+ else if (Compress == Extension)
+ {
+ std::string::size_type const found = FileName.find_last_of('.');
+ std::string ext;
+ if (found != std::string::npos)
{
- struct stat Buf;
- if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
- unlink(FileName.c_str());
- iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
- 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();
+ }
}
-
- case WriteExists:
- iFd = open(FileName.c_str(),O_RDWR);
- break;
+ 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
+ {
+ 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:
+ // 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())
+ return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+ }
- case WriteAny:
- iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
- break;
+ 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());
- case WriteTemp:
+ if ((Mode & Atomic) == Atomic)
+ {
+ Flags |= Replace;
+ char *name = strdup((FileName + ".XXXXXX").c_str());
+ TemporaryFileName = string(mktemp(name));
+ free(name);
+ }
+ else if ((Mode & (Exclusive | Create)) == (Exclusive | Create))
+ {
+ // for atomic, this will be done by rename in Close()
unlink(FileName.c_str());
- iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
- break;
- }
+ }
+ if ((Mode & Empty) == Empty)
+ {
+ struct stat Buf;
+ if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
+ unlink(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);
+
+ if_FLAGGED_SET(Create, O_CREAT);
+ if_FLAGGED_SET(Empty, O_TRUNC);
+ if_FLAGGED_SET(Exclusive, O_EXCL);
+ else if_FLAGGED_SET(Atomic, O_EXCL);
+ #undef if_FLAGGED_SET
+
+ if (TemporaryFileName.empty() == false)
+ iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
+ else
+ iFd = open(FileName.c_str(), fileflags, Perms);
+
+ if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false)
+ {
+ if (iFd != -1)
+ {
+ close (iFd);
+ iFd = -1;
+ }
+ return _error->Errno("open",_("Could not open file %s"), FileName.c_str());
+ }
- if (iFd < 0)
- return _error->Errno("open",_("Could not open file %s"),FileName.c_str());
-
this->FileName = FileName;
SetCloseExec(iFd,true);
return true;
}
+ /*}}}*/
+// FileFd::OpenDescriptor - Open a filedescriptor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+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());
-bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose)
+ 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 (Mode == ReadOnlyGzip) {
- gz = gzdopen (iFd, "r");
- if (gz == NULL) {
- if (AutoClose)
- close (iFd);
- return _error->Errno("gzdopen",_("Could not open file descriptor %d"),
- Fd);
- }
+ if (OpenInternDescriptor(Mode, compressor) == false)
+ {
+ if (AutoClose)
+ close (iFd);
+ return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd);
}
this->FileName = "";
return true;
}
+bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
+{
+ d->compressor = compressor;
+ if (compressor.Name == "." || compressor.Binary.empty() == true)
+ return true;
+#if APT_USE_ZLIB
+ else if (compressor.Name == "gzip")
+ {
+ if ((Mode & ReadWrite) == ReadWrite)
+ d->gz = gzdopen(iFd, "r+");
+ else if ((Mode & WriteOnly) == WriteOnly)
+ d->gz = gzdopen(iFd, "w");
+ else
+ d->gz = gzdopen (iFd, "r");
+ if (d->gz == NULL)
+ return false;
+ Flags |= Compressed;
+ return true;
+ }
+#endif
+
+ if ((Mode & ReadWrite) == ReadWrite)
+ return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str());
+
+ bool const Comp = (Mode & WriteOnly) == WriteOnly;
+ // Handle 'decompression' of empty files
+ if (Comp == false)
+ {
+ struct stat Buf;
+ fstat(iFd, &Buf);
+ if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false)
+ return true;
+
+ // We don't need the file open - instead let the compressor open it
+ // as he properly knows better how to efficiently read from 'his' file
+ if (FileName.empty() == false)
+ close(iFd);
+ }
+
+ // Create a data pipe
+ int Pipe[2] = {-1,-1};
+ if (pipe(Pipe) != 0)
+ return _error->Errno("pipe",_("Failed to create subprocess IPC"));
+ for (int J = 0; J != 2; J++)
+ SetCloseExec(Pipe[J],true);
+
+ d->compressed_fd = iFd;
+ d->pipe = true;
+
+ if (Comp == true)
+ iFd = Pipe[1];
+ else
+ iFd = Pipe[0];
+
+ // The child..
+ d->compressor_pid = ExecFork();
+ if (d->compressor_pid == 0)
+ {
+ if (Comp == true)
+ {
+ dup2(d->compressed_fd,STDOUT_FILENO);
+ dup2(Pipe[0],STDIN_FILENO);
+ }
+ else
+ {
+ if (FileName.empty() == true)
+ dup2(d->compressed_fd,STDIN_FILENO);
+ dup2(Pipe[1],STDOUT_FILENO);
+ }
+
+ SetCloseExec(STDOUT_FILENO,false);
+ SetCloseExec(STDIN_FILENO,false);
+
+ std::vector<char const*> Args;
+ Args.push_back(compressor.Binary.c_str());
+ std::vector<std::string> const * const addArgs =
+ (Comp == true) ? &(compressor.CompressArgs) : &(compressor.UncompressArgs);
+ for (std::vector<std::string>::const_iterator a = addArgs->begin();
+ a != addArgs->end(); ++a)
+ Args.push_back(a->c_str());
+ if (Comp == false && FileName.empty() == false)
+ {
+ Args.push_back("--stdout");
+ if (TemporaryFileName.empty() == false)
+ Args.push_back(TemporaryFileName.c_str());
+ else
+ Args.push_back(FileName.c_str());
+ }
+ Args.push_back(NULL);
+
+ execvp(Args[0],(char **)&Args[0]);
+ cerr << _("Failed to exec compressor ") << Args[0] << endl;
+ _exit(100);
+ }
+ if (Comp == true)
+ close(Pipe[0]);
+ else
+ close(Pipe[1]);
+ if (Comp == true || FileName.empty() == true)
+ close(d->compressed_fd);
+
+ return true;
+}
/*}}}*/
// FileFd::~File - Closes the file /*{{{*/
// ---------------------------------------------------------------------
@@ -817,12 +1046,14 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
errno = 0;
if (Actual != 0)
*Actual = 0;
-
+ *((char *)To) = '\0';
do
{
- if (gz != NULL)
- Res = gzread(gz,To,Size);
+#if APT_USE_ZLIB
+ if (d->gz != NULL)
+ Res = gzread(d->gz,To,Size);
else
+#endif
Res = read(iFd,To,Size);
if (Res < 0 && errno == EINTR)
continue;
@@ -853,6 +1084,31 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
return _error->Error(_("read, still have %llu to read but none left"), Size);
}
/*}}}*/
+// FileFd::ReadLine - Read a complete line from the file /*{{{*/
+// ---------------------------------------------------------------------
+/* Beware: This method can be quiet slow for big buffers on UNcompressed
+ files because of the naive implementation! */
+char* FileFd::ReadLine(char *To, unsigned long long const Size)
+{
+ *To = '\0';
+#if APT_USE_ZLIB
+ if (d->gz != NULL)
+ return gzgets(d->gz, To, Size);
+#endif
+
+ unsigned long long read = 0;
+ if (Read(To, Size, &read) == false)
+ return NULL;
+ char* c = To;
+ for (; *c != '\n' && *c != '\0' && read != 0; --read, ++c)
+ ; // find the end of the line
+ if (*c != '\0')
+ *c = '\0';
+ if (read != 0)
+ Seek(Tell() - read);
+ return To;
+}
+ /*}}}*/
// FileFd::Write - Write to the file /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -862,9 +1118,11 @@ bool FileFd::Write(const void *From,unsigned long long Size)
errno = 0;
do
{
- if (gz != NULL)
- Res = gzwrite(gz,From,Size);
+#if APT_USE_ZLIB
+ if (d->gz != NULL)
+ Res = gzwrite(d->gz,From,Size);
else
+#endif
Res = write(iFd,From,Size);
if (Res < 0 && errno == EINTR)
continue;
@@ -891,10 +1149,38 @@ bool FileFd::Write(const void *From,unsigned long long Size)
/* */
bool FileFd::Seek(unsigned long long To)
{
+ if (d->pipe == true)
+ {
+ if ((d->openmode & ReadOnly) != ReadOnly)
+ return _error->Error("Reopen is only implemented for read-only files!");
+ close(iFd);
+ iFd = 0;
+ if (TemporaryFileName.empty() == false)
+ iFd = open(TemporaryFileName.c_str(), O_RDONLY);
+ else if (FileName.empty() == false)
+ iFd = open(FileName.c_str(), O_RDONLY);
+ else
+ {
+ if (d->compressed_fd > 0)
+ if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
+ iFd = d->compressed_fd;
+ if (iFd <= 0)
+ return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
+ }
+
+ if (OpenInternDescriptor(d->openmode, d->compressor) == false)
+ return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str());
+
+ if (To != 0)
+ return Skip(To);
+ return true;
+ }
int res;
- if (gz)
- res = gzseek(gz,To,SEEK_SET);
+#if APT_USE_ZLIB
+ if (d->gz)
+ res = gzseek(d->gz,To,SEEK_SET);
else
+#endif
res = lseek(iFd,To,SEEK_SET);
if (res != (signed)To)
{
@@ -911,9 +1197,11 @@ bool FileFd::Seek(unsigned long long To)
bool FileFd::Skip(unsigned long long Over)
{
int res;
- if (gz)
- res = gzseek(gz,Over,SEEK_CUR);
+#if APT_USE_ZLIB
+ if (d->gz != NULL)
+ res = gzseek(d->gz,Over,SEEK_CUR);
else
+#endif
res = lseek(iFd,Over,SEEK_CUR);
if (res < 0)
{
@@ -929,7 +1217,7 @@ bool FileFd::Skip(unsigned long long Over)
/* */
bool FileFd::Truncate(unsigned long long To)
{
- if (gz)
+ if (d->gz != NULL)
{
Flags |= Fail;
return _error->Error("Truncating gzipped files is not implemented (%s)", FileName.c_str());
@@ -949,9 +1237,11 @@ bool FileFd::Truncate(unsigned long long To)
unsigned long long FileFd::Tell()
{
off_t Res;
- if (gz)
- Res = gztell(gz);
+#if APT_USE_ZLIB
+ if (d->gz != NULL)
+ Res = gztell(d->gz);
else
+#endif
Res = lseek(iFd,0,SEEK_CUR);
if (Res == (off_t)-1)
_error->Errno("lseek","Failed to determine the current file position");
@@ -964,9 +1254,19 @@ unsigned long long FileFd::Tell()
unsigned long long FileFd::FileSize()
{
struct stat Buf;
-
- if (fstat(iFd,&Buf) != 0)
+ if (d->pipe == false && fstat(iFd,&Buf) != 0)
return _error->Errno("fstat","Unable to determine the file size");
+
+ // for compressor pipes st_size is undefined and at 'best' zero
+ if (d->pipe == true || S_ISFIFO(Buf.st_mode))
+ {
+ // we set it here, too, as we get the info here for free
+ // in theory the Open-methods should take care of it already
+ d->pipe = true;
+ if (stat(FileName.c_str(), &Buf) != 0)
+ return _error->Errno("stat","Unable to determine the file size");
+ }
+
return Buf.st_size;
}
/*}}}*/
@@ -977,10 +1277,25 @@ unsigned long long FileFd::Size()
{
unsigned long long size = FileSize();
+ // for compressor pipes st_size is undefined and at 'best' zero,
+ // so we 'read' the content and 'seek' back - see there
+ if (d->pipe == true)
+ {
+ // FIXME: If we have read first and then FileSize() the report is wrong
+ size = 0;
+ char ignore[1000];
+ unsigned long long read = 0;
+ do {
+ Read(ignore, sizeof(ignore), &read);
+ size += read;
+ } while(read != 0);
+ Seek(0);
+ }
+#if APT_USE_ZLIB
// only check gzsize if we are actually a gzip file, just checking for
- // "gz" is not sufficient as uncompressed files will be opened with
+ // "gz" is not sufficient as uncompressed files could be opened with
// gzopen in "direct" mode as well
- if (gz && !gzdirect(gz) && size > 0)
+ else if (d->gz && !gzdirect(d->gz) && size > 0)
{
/* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
* this ourselves; the original (uncompressed) file size is the last 32
@@ -1004,24 +1319,58 @@ unsigned long long FileFd::Size()
return _error->Errno("lseek","Unable to seek in gzipped file");
return size;
}
+#endif
return size;
}
/*}}}*/
+// FileFd::ModificationTime - Return the time of last touch /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+time_t FileFd::ModificationTime()
+{
+ struct stat Buf;
+ if (d->pipe == false && fstat(iFd,&Buf) != 0)
+ {
+ _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+ return 0;
+ }
+
+ // for compressor pipes st_size is undefined and at 'best' zero
+ if (d->pipe == true || S_ISFIFO(Buf.st_mode))
+ {
+ // we set it here, too, as we get the info here for free
+ // in theory the Open-methods should take care of it already
+ d->pipe = true;
+ if (stat(FileName.c_str(), &Buf) != 0)
+ {
+ _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+ return 0;
+ }
+ }
+
+ return Buf.st_mtime;
+}
+ /*}}}*/
// FileFd::Close - Close the file if the close flag is set /*{{{*/
// ---------------------------------------------------------------------
/* */
bool FileFd::Close()
{
+ if (iFd == -1)
+ return true;
+
bool Res = true;
if ((Flags & AutoClose) == AutoClose)
{
- if (gz != NULL) {
- int const e = gzclose(gz);
+#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 (e != 0 && e != Z_BUF_ERROR)
Res &= _error->Errno("close",_("Problem closing the gzip file %s"), FileName.c_str());
} else
+#endif
if (iFd > 0 && close(iFd) != 0)
Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
}
@@ -1031,16 +1380,23 @@ bool FileFd::Close()
Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str());
FileName = TemporaryFileName; // for the unlink() below.
+ TemporaryFileName.clear();
}
iFd = -1;
- gz = NULL;
if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
FileName.empty() == false)
if (unlink(FileName.c_str()) != 0)
Res &= _error->WarningE("unlnk",_("Problem unlinking the file %s"), FileName.c_str());
+ if (d != NULL)
+ {
+ if (d->compressor_pid > 0)
+ ExecWait(d->compressor_pid, "FileFdCompressor", true);
+ delete d;
+ d = NULL;
+ }
return Res;
}
@@ -1057,3 +1413,5 @@ bool FileFd::Sync()
return true;
}
/*}}}*/
+
+gzFile FileFd::gzFd() { return (gzFile) d->gz; }
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 0d0451a46..147535df1 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -22,30 +22,51 @@
#define PKGLIB_FILEUTL_H
#include <apt-pkg/macros.h>
+#include <apt-pkg/aptconfiguration.h>
#include <string>
#include <vector>
#include <zlib.h>
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
/* Define this for python-apt */
#define APT_HAS_GZIP 1
+class FileFdPrivate;
class FileFd
{
protected:
int iFd;
enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2),
- HitEof = (1<<3), Replace = (1<<4) };
+ HitEof = (1<<3), Replace = (1<<4), Compressed = (1<<5) };
unsigned long Flags;
std::string FileName;
std::string TemporaryFileName;
- gzFile gz;
public:
- enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp,ReadOnlyGzip,
- WriteAtomic};
+ enum OpenMode {
+ ReadOnly = (1 << 0),
+ WriteOnly = (1 << 1),
+ ReadWrite = ReadOnly | WriteOnly,
+
+ Create = (1 << 2),
+ Exclusive = (1 << 3),
+ Atomic = Exclusive | (1 << 4),
+ Empty = (1 << 5),
+
+ WriteEmpty = ReadWrite | Create | Empty,
+ WriteExists = ReadWrite,
+ WriteAny = ReadWrite | Create,
+ WriteTemp = ReadWrite | Create | Exclusive,
+ ReadOnlyGzip,
+ WriteAtomic = ReadWrite | Create | Atomic
+ };
+ enum CompressMode { Auto = 'A', None = 'N', Extension = 'E', Gzip = 'G', Bzip2 = 'B', Lzma = 'L', Xz = 'X' };
inline bool Read(void *To,unsigned long long Size,bool AllowEof)
{
@@ -55,6 +76,7 @@ class FileFd
return Read(To,Size);
}
bool Read(void *To,unsigned long long Size,unsigned long long *Actual = 0);
+ char* ReadLine(char *To, unsigned long long const Size);
bool Write(const void *From,unsigned long long Size);
bool Seek(unsigned long long To);
bool Skip(unsigned long long To);
@@ -62,6 +84,7 @@ class FileFd
unsigned long long Tell();
unsigned long long Size();
unsigned long long FileSize();
+ time_t ModificationTime();
/* You want to use 'unsigned long long' if you are talking about a file
to be able to support large files (>2 or >4 GB) properly.
@@ -77,30 +100,54 @@ class FileFd
return T;
}
- bool Open(std::string FileName,OpenMode Mode,unsigned long Perms = 0666);
- bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false);
+ bool Open(std::string FileName,unsigned int const Mode,CompressMode Compress,unsigned long const Perms = 0666);
+ bool Open(std::string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor,unsigned long const Perms = 0666);
+ inline bool Open(std::string const &FileName,unsigned int const Mode, unsigned long const Perms = 0666) {
+ return Open(FileName, Mode, None, Perms);
+ };
+ bool OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose=false);
+ bool OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false);
+ inline bool OpenDescriptor(int Fd, unsigned int const Mode, bool AutoClose=false) {
+ return OpenDescriptor(Fd, Mode, None, AutoClose);
+ };
bool Close();
bool Sync();
// Simple manipulators
inline int Fd() {return iFd;};
inline void Fd(int fd) {iFd = fd;};
- inline gzFile gzFd() {return gz;};
+ __deprecated gzFile gzFd();
+
inline bool IsOpen() {return iFd >= 0;};
inline bool Failed() {return (Flags & Fail) == Fail;};
inline void EraseOnFailure() {Flags |= DelOnFail;};
inline void OpFail() {Flags |= Fail;};
inline bool Eof() {return (Flags & HitEof) == HitEof;};
+ inline bool IsCompressed() {return (Flags & Compressed) == Compressed;};
inline std::string &Name() {return FileName;};
- FileFd(std::string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1),
- Flags(0), gz(NULL)
+ FileFd(std::string FileName,unsigned int const Mode,unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL)
{
- Open(FileName,Mode,Perms);
+ Open(FileName,Mode, None, Perms);
+ };
+ FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL)
+ {
+ Open(FileName,Mode, Compress, Perms);
+ };
+ FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {};
+ FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL)
+ {
+ OpenDescriptor(Fd, Mode, Compress);
+ };
+ FileFd(int const Fd, bool const AutoClose) : iFd(-1), Flags(0), d(NULL)
+ {
+ OpenDescriptor(Fd, ReadWrite, None, AutoClose);
};
- FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose), gz(NULL) {};
- FileFd(int Fd,bool) : iFd(Fd), Flags(0), gz(NULL) {};
virtual ~FileFd();
+
+ private:
+ FileFdPrivate* d;
+ bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor);
};
bool RunScripts(const char *Cnf);
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 81851dede..b206eccb8 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -22,6 +22,12 @@
#include <vector>
#include <cstring>
+
+#ifndef APT_8_CLEANER_HEADERS
+using std::min;
+using std::vector;
+#endif
+
// helper class that contains hash function name
// and hash
class HashString
diff --git a/apt-pkg/contrib/hashsum_template.h b/apt-pkg/contrib/hashsum_template.h
index 27d192b82..6301ac9d0 100644
--- a/apt-pkg/contrib/hashsum_template.h
+++ b/apt-pkg/contrib/hashsum_template.h
@@ -15,6 +15,11 @@
#include <algorithm>
#include <stdint.h>
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
template<int N>
class HashSumValue
{
diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h
index a207da4e4..25631b166 100644
--- a/apt-pkg/contrib/md5.h
+++ b/apt-pkg/contrib/md5.h
@@ -31,6 +31,11 @@
#include "hashsum_template.h"
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
typedef HashSumValue<128> MD5SumValue;
class MD5Summation : public SummationImplementation
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index f76169a92..a67ab3698 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -66,7 +66,7 @@ MMap::~MMap()
bool MMap::Map(FileFd &Fd)
{
iSize = Fd.Size();
-
+
// Set the permissions.
int Prot = PROT_READ;
int Map = MAP_SHARED;
@@ -77,7 +77,18 @@ bool MMap::Map(FileFd &Fd)
if (iSize == 0)
return _error->Error(_("Can't mmap an empty file"));
-
+
+ // We can't mmap compressed fd's directly, so we need to read it completely
+ if (Fd.IsCompressed() == true)
+ {
+ if ((Flags & ReadOnly) != ReadOnly)
+ return _error->Error("Compressed file %s can only be mapped readonly", Fd.Name().c_str());
+ Base = new unsigned char[iSize];
+ if (Fd.Seek(0L) == false || Fd.Read(Base, iSize) == false)
+ return false;
+ return true;
+ }
+
// Map it.
Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
if (Base == (void *)-1)
@@ -86,6 +97,13 @@ bool MMap::Map(FileFd &Fd)
{
// The filesystem doesn't support this particular kind of mmap.
// So we allocate a buffer and read the whole file into it.
+ if ((Flags & ReadOnly) == ReadOnly)
+ {
+ // for readonly, we don't need sync, so make it simple
+ Base = new unsigned char[iSize];
+ return Fd.Read(Base, iSize);
+ }
+ // FIXME: Writing to compressed fd's ?
int const dupped_fd = dup(Fd.Fd());
if (dupped_fd == -1)
return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd());
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index 2ed4a95f8..6bd4a2d86 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -28,6 +28,11 @@
#include <string>
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/fileutl.h>
+using std::string;
+#endif
+
class FileFd;
/* This should be a 32 bit type, larger tyes use too much ram and smaller
diff --git a/apt-pkg/contrib/netrc.h b/apt-pkg/contrib/netrc.h
index 7b94eba88..5931d4a42 100644
--- a/apt-pkg/contrib/netrc.h
+++ b/apt-pkg/contrib/netrc.h
@@ -16,6 +16,10 @@
#include <string>
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/strutl.h>
+#endif
+
#define DOT_CHAR "."
#define DIR_CHAR "/"
diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h
index 7635719bc..3a6943aee 100644
--- a/apt-pkg/contrib/progress.h
+++ b/apt-pkg/contrib/progress.h
@@ -25,6 +25,10 @@
#include <string>
#include <sys/time.h>
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
class Configuration;
class OpProgress
{
diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h
index b4b139a22..a8d55eb13 100644
--- a/apt-pkg/contrib/sha1.h
+++ b/apt-pkg/contrib/sha1.h
@@ -20,6 +20,11 @@
#include "hashsum_template.h"
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
typedef HashSumValue<160> SHA1SumValue;
class SHA1Summation : public SummationImplementation
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index 93f4bef4f..337139d5d 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -27,6 +27,12 @@
#include "macros.h"
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::vector;
+using std::ostream;
+#endif
+
bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest);
char *_strstrip(char *String);
char *_strtabexpand(char *String,size_t Len);