|
@@ -81,6 +81,31 @@ class FileFdPrivate {
|
|
|
FileFdPrivate() : gz(NULL), bz2(NULL),
|
|
FileFdPrivate() : gz(NULL), bz2(NULL),
|
|
|
compressed_fd(-1), compressor_pid(-1), pipe(false),
|
|
compressed_fd(-1), compressor_pid(-1), pipe(false),
|
|
|
openmode(0), seekpos(0) {};
|
|
openmode(0), seekpos(0) {};
|
|
|
|
|
+ bool CloseDown(std::string const &FileName)
|
|
|
|
|
+ {
|
|
|
|
|
+ bool Res = true;
|
|
|
|
|
+#ifdef HAVE_ZLIB
|
|
|
|
|
+ if (gz != NULL) {
|
|
|
|
|
+ int const e = gzclose(gz);
|
|
|
|
|
+ gz = NULL;
|
|
|
|
|
+ // gzdclose() 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());
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef HAVE_BZ2
|
|
|
|
|
+ if (bz2 != NULL) {
|
|
|
|
|
+ BZ2_bzclose(bz2);
|
|
|
|
|
+ bz2 = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ if (compressor_pid > 0)
|
|
|
|
|
+ ExecWait(compressor_pid, "FileFdCompressor", true);
|
|
|
|
|
+ compressor_pid = -1;
|
|
|
|
|
+
|
|
|
|
|
+ return Res;
|
|
|
|
|
+ }
|
|
|
|
|
+ ~FileFdPrivate() { CloseDown(""); }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
|
|
// RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
|
|
@@ -827,6 +852,26 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
|
|
|
|
|
|
|
+// StartsWithGPGClearTextSignature - Check if a file is Pgp/GPG clearsigned /*{{{*/
|
|
|
|
|
+// ---------------------------------------------------------------------
|
|
|
|
|
+/* */
|
|
|
|
|
+bool StartsWithGPGClearTextSignature(string const &FileName)
|
|
|
|
|
+{
|
|
|
|
|
+ static const char* SIGMSG = "-----BEGIN PGP SIGNED MESSAGE-----\n";
|
|
|
|
|
+ char buffer[strlen(SIGMSG)+1];
|
|
|
|
|
+ FILE* gpg = fopen(FileName.c_str(), "r");
|
|
|
|
|
+ if (gpg == NULL)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ char const * const test = fgets(buffer, sizeof(buffer), gpg);
|
|
|
|
|
+ fclose(gpg);
|
|
|
|
|
+ if (test == NULL || strcmp(buffer, SIGMSG) != 0)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
// FileFd::Open - Open a file /*{{{*/
|
|
// FileFd::Open - Open a file /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* The most commonly used open mode combinations are given with Mode */
|
|
/* The most commonly used open mode combinations are given with Mode */
|
|
@@ -905,8 +950,6 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress,
|
|
|
bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
|
|
bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
|
|
|
{
|
|
{
|
|
|
Close();
|
|
Close();
|
|
|
- d = new FileFdPrivate;
|
|
|
|
|
- d->openmode = Mode;
|
|
|
|
|
Flags = AutoClose;
|
|
Flags = AutoClose;
|
|
|
|
|
|
|
|
if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
|
|
if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
|
|
@@ -1000,10 +1043,21 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compre
|
|
|
bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
|
|
bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
|
|
|
{
|
|
{
|
|
|
Close();
|
|
Close();
|
|
|
- d = new FileFdPrivate;
|
|
|
|
|
- d->openmode = Mode;
|
|
|
|
|
Flags = (AutoClose) ? FileFd::AutoClose : 0;
|
|
Flags = (AutoClose) ? FileFd::AutoClose : 0;
|
|
|
- iFd = Fd;
|
|
|
|
|
|
|
+ if (AutoClose == false && (
|
|
|
|
|
+#ifdef HAVE_ZLIB
|
|
|
|
|
+ compressor.Name == "gzip" ||
|
|
|
|
|
+#endif
|
|
|
|
|
+#ifdef HAVE_BZ2
|
|
|
|
|
+ compressor.Name == "bzip2" ||
|
|
|
|
|
+#endif
|
|
|
|
|
+ false))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Need to duplicate fd here or gzclose for cleanup will close the fd as well
|
|
|
|
|
+ iFd = dup(Fd);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ iFd = Fd;
|
|
|
this->FileName = "";
|
|
this->FileName = "";
|
|
|
if (OpenInternDescriptor(Mode, compressor) == false)
|
|
if (OpenInternDescriptor(Mode, compressor) == false)
|
|
|
{
|
|
{
|
|
@@ -1015,12 +1069,24 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration:
|
|
|
}
|
|
}
|
|
|
bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
|
|
bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
|
|
|
{
|
|
{
|
|
|
- d->compressor = compressor;
|
|
|
|
|
if (compressor.Name == "." || compressor.Binary.empty() == true)
|
|
if (compressor.Name == "." || compressor.Binary.empty() == true)
|
|
|
return true;
|
|
return true;
|
|
|
|
|
+
|
|
|
|
|
+ if (d == NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ d = new FileFdPrivate();
|
|
|
|
|
+ d->openmode = Mode;
|
|
|
|
|
+ d->compressor = compressor;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- else if (compressor.Name == "gzip")
|
|
|
|
|
|
|
+ if (compressor.Name == "gzip")
|
|
|
{
|
|
{
|
|
|
|
|
+ if (d->gz != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ gzclose(d->gz);
|
|
|
|
|
+ d->gz = NULL;
|
|
|
|
|
+ }
|
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
|
d->gz = gzdopen(iFd, "r+");
|
|
d->gz = gzdopen(iFd, "r+");
|
|
|
else if ((Mode & WriteOnly) == WriteOnly)
|
|
else if ((Mode & WriteOnly) == WriteOnly)
|
|
@@ -1034,8 +1100,13 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- else if (compressor.Name == "bzip2")
|
|
|
|
|
|
|
+ if (compressor.Name == "bzip2")
|
|
|
{
|
|
{
|
|
|
|
|
+ if (d->bz2 != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ BZ2_bzclose(d->bz2);
|
|
|
|
|
+ d->bz2 = NULL;
|
|
|
|
|
+ }
|
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
|
d->bz2 = BZ2_bzdopen(iFd, "r+");
|
|
d->bz2 = BZ2_bzdopen(iFd, "r+");
|
|
|
else if ((Mode & WriteOnly) == WriteOnly)
|
|
else if ((Mode & WriteOnly) == WriteOnly)
|
|
@@ -1049,14 +1120,20 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+ // collect zombies here in case we reopen
|
|
|
|
|
+ if (d->compressor_pid > 0)
|
|
|
|
|
+ ExecWait(d->compressor_pid, "FileFdCompressor", true);
|
|
|
|
|
|
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
if ((Mode & ReadWrite) == ReadWrite)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str());
|
|
return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
bool const Comp = (Mode & WriteOnly) == WriteOnly;
|
|
bool const Comp = (Mode & WriteOnly) == WriteOnly;
|
|
|
- // Handle 'decompression' of empty files
|
|
|
|
|
if (Comp == false)
|
|
if (Comp == false)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Handle 'decompression' of empty files
|
|
|
struct stat Buf;
|
|
struct stat Buf;
|
|
|
fstat(iFd, &Buf);
|
|
fstat(iFd, &Buf);
|
|
|
if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false)
|
|
if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false)
|
|
@@ -1065,13 +1142,19 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
// We don't need the file open - instead let the compressor open it
|
|
// 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
|
|
// as he properly knows better how to efficiently read from 'his' file
|
|
|
if (FileName.empty() == false)
|
|
if (FileName.empty() == false)
|
|
|
|
|
+ {
|
|
|
close(iFd);
|
|
close(iFd);
|
|
|
|
|
+ iFd = -1;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Create a data pipe
|
|
// Create a data pipe
|
|
|
int Pipe[2] = {-1,-1};
|
|
int Pipe[2] = {-1,-1};
|
|
|
if (pipe(Pipe) != 0)
|
|
if (pipe(Pipe) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Errno("pipe",_("Failed to create subprocess IPC"));
|
|
return _error->Errno("pipe",_("Failed to create subprocess IPC"));
|
|
|
|
|
+ }
|
|
|
for (int J = 0; J != 2; J++)
|
|
for (int J = 0; J != 2; J++)
|
|
|
SetCloseExec(Pipe[J],true);
|
|
SetCloseExec(Pipe[J],true);
|
|
|
|
|
|
|
@@ -1098,6 +1181,12 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
dup2(d->compressed_fd,STDIN_FILENO);
|
|
dup2(d->compressed_fd,STDIN_FILENO);
|
|
|
dup2(Pipe[1],STDOUT_FILENO);
|
|
dup2(Pipe[1],STDOUT_FILENO);
|
|
|
}
|
|
}
|
|
|
|
|
+ int const nullfd = open("/dev/null", O_WRONLY);
|
|
|
|
|
+ if (nullfd != -1)
|
|
|
|
|
+ {
|
|
|
|
|
+ dup2(nullfd,STDERR_FILENO);
|
|
|
|
|
+ close(nullfd);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
SetCloseExec(STDOUT_FILENO,false);
|
|
SetCloseExec(STDOUT_FILENO,false);
|
|
|
SetCloseExec(STDIN_FILENO,false);
|
|
SetCloseExec(STDIN_FILENO,false);
|
|
@@ -1127,8 +1216,6 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
close(Pipe[0]);
|
|
close(Pipe[0]);
|
|
|
else
|
|
else
|
|
|
close(Pipe[1]);
|
|
close(Pipe[1]);
|
|
|
- if (Comp == true || FileName.empty() == true)
|
|
|
|
|
- close(d->compressed_fd);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -1140,6 +1227,12 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
|
|
|
FileFd::~FileFd()
|
|
FileFd::~FileFd()
|
|
|
{
|
|
{
|
|
|
Close();
|
|
Close();
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ d->CloseDown(FileName);
|
|
|
|
|
+ delete d;
|
|
|
|
|
+ d = NULL;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
// FileFd::Read - Read a bit of the file /*{{{*/
|
|
// FileFd::Read - Read a bit of the file /*{{{*/
|
|
@@ -1156,12 +1249,12 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
Res = gzread(d->gz,To,Size);
|
|
Res = gzread(d->gz,To,Size);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- if (d->bz2 != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->bz2 != NULL)
|
|
|
Res = BZ2_bzread(d->bz2,To,Size);
|
|
Res = BZ2_bzread(d->bz2,To,Size);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
@@ -1173,7 +1266,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
|
|
|
continue;
|
|
continue;
|
|
|
Flags |= Fail;
|
|
Flags |= Fail;
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
char const * const errmsg = gzerror(d->gz, &err);
|
|
char const * const errmsg = gzerror(d->gz, &err);
|
|
@@ -1182,7 +1275,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- if (d->bz2 != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->bz2 != NULL)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
|
|
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
|
|
@@ -1195,7 +1288,8 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
|
|
|
|
|
|
|
|
To = (char *)To + Res;
|
|
To = (char *)To + Res;
|
|
|
Size -= Res;
|
|
Size -= Res;
|
|
|
- d->seekpos += Res;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->seekpos += Res;
|
|
|
if (Actual != 0)
|
|
if (Actual != 0)
|
|
|
*Actual += Res;
|
|
*Actual += Res;
|
|
|
}
|
|
}
|
|
@@ -1223,7 +1317,7 @@ char* FileFd::ReadLine(char *To, unsigned long long const Size)
|
|
|
{
|
|
{
|
|
|
*To = '\0';
|
|
*To = '\0';
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
return gzgets(d->gz, To, Size);
|
|
return gzgets(d->gz, To, Size);
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
@@ -1254,12 +1348,12 @@ bool FileFd::Write(const void *From,unsigned long long Size)
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
Res = gzwrite(d->gz,From,Size);
|
|
Res = gzwrite(d->gz,From,Size);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- if (d->bz2 != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->bz2 != NULL)
|
|
|
Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
|
|
Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
@@ -1270,7 +1364,7 @@ bool FileFd::Write(const void *From,unsigned long long Size)
|
|
|
{
|
|
{
|
|
|
Flags |= Fail;
|
|
Flags |= Fail;
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
char const * const errmsg = gzerror(d->gz, &err);
|
|
char const * const errmsg = gzerror(d->gz, &err);
|
|
@@ -1279,7 +1373,7 @@ bool FileFd::Write(const void *From,unsigned long long Size)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- if (d->bz2 != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->bz2 != NULL)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
|
|
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
|
|
@@ -1292,7 +1386,8 @@ bool FileFd::Write(const void *From,unsigned long long Size)
|
|
|
|
|
|
|
|
From = (char *)From + Res;
|
|
From = (char *)From + Res;
|
|
|
Size -= Res;
|
|
Size -= Res;
|
|
|
- d->seekpos += Res;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->seekpos += Res;
|
|
|
}
|
|
}
|
|
|
while (Res > 0 && Size > 0);
|
|
while (Res > 0 && Size > 0);
|
|
|
|
|
|
|
@@ -1330,11 +1425,11 @@ bool FileFd::Write(int Fd, const void *From, unsigned long long Size)
|
|
|
/* */
|
|
/* */
|
|
|
bool FileFd::Seek(unsigned long long To)
|
|
bool FileFd::Seek(unsigned long long To)
|
|
|
{
|
|
{
|
|
|
- if (d->pipe == true
|
|
|
|
|
|
|
+ if (d != NULL && (d->pipe == true
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- || d->bz2 != NULL
|
|
|
|
|
|
|
+ || d->bz2 != NULL
|
|
|
#endif
|
|
#endif
|
|
|
- )
|
|
|
|
|
|
|
+ ))
|
|
|
{
|
|
{
|
|
|
// Our poor man seeking in pipes is costly, so try to avoid it
|
|
// Our poor man seeking in pipes is costly, so try to avoid it
|
|
|
unsigned long long seekpos = Tell();
|
|
unsigned long long seekpos = Tell();
|
|
@@ -1344,13 +1439,17 @@ bool FileFd::Seek(unsigned long long To)
|
|
|
return Skip(To - seekpos);
|
|
return Skip(To - seekpos);
|
|
|
|
|
|
|
|
if ((d->openmode & ReadOnly) != ReadOnly)
|
|
if ((d->openmode & ReadOnly) != ReadOnly)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Error("Reopen is only implemented for read-only files!");
|
|
return _error->Error("Reopen is only implemented for read-only files!");
|
|
|
|
|
+ }
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
if (d->bz2 != NULL)
|
|
if (d->bz2 != NULL)
|
|
|
BZ2_bzclose(d->bz2);
|
|
BZ2_bzclose(d->bz2);
|
|
|
#endif
|
|
#endif
|
|
|
- close(iFd);
|
|
|
|
|
- iFd = 0;
|
|
|
|
|
|
|
+ if (iFd != -1)
|
|
|
|
|
+ close(iFd);
|
|
|
|
|
+ iFd = -1;
|
|
|
if (TemporaryFileName.empty() == false)
|
|
if (TemporaryFileName.empty() == false)
|
|
|
iFd = open(TemporaryFileName.c_str(), O_RDONLY);
|
|
iFd = open(TemporaryFileName.c_str(), O_RDONLY);
|
|
|
else if (FileName.empty() == false)
|
|
else if (FileName.empty() == false)
|
|
@@ -1360,12 +1459,18 @@ bool FileFd::Seek(unsigned long long To)
|
|
|
if (d->compressed_fd > 0)
|
|
if (d->compressed_fd > 0)
|
|
|
if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
|
|
if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
|
|
|
iFd = d->compressed_fd;
|
|
iFd = d->compressed_fd;
|
|
|
- if (iFd <= 0)
|
|
|
|
|
|
|
+ if (iFd < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
|
|
return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (OpenInternDescriptor(d->openmode, d->compressor) == false)
|
|
if (OpenInternDescriptor(d->openmode, d->compressor) == false)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str());
|
|
return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (To != 0)
|
|
if (To != 0)
|
|
|
return Skip(To);
|
|
return Skip(To);
|
|
@@ -1375,7 +1480,7 @@ bool FileFd::Seek(unsigned long long To)
|
|
|
}
|
|
}
|
|
|
int res;
|
|
int res;
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz)
|
|
|
res = gzseek(d->gz,To,SEEK_SET);
|
|
res = gzseek(d->gz,To,SEEK_SET);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
@@ -1386,7 +1491,8 @@ bool FileFd::Seek(unsigned long long To)
|
|
|
return _error->Error("Unable to seek to %llu", To);
|
|
return _error->Error("Unable to seek to %llu", To);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- d->seekpos = To;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->seekpos = To;
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
@@ -1395,11 +1501,11 @@ bool FileFd::Seek(unsigned long long To)
|
|
|
/* */
|
|
/* */
|
|
|
bool FileFd::Skip(unsigned long long Over)
|
|
bool FileFd::Skip(unsigned long long Over)
|
|
|
{
|
|
{
|
|
|
- if (d->pipe == true
|
|
|
|
|
|
|
+ if (d != NULL && (d->pipe == true
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- || d->bz2 != NULL
|
|
|
|
|
|
|
+ || d->bz2 != NULL
|
|
|
#endif
|
|
#endif
|
|
|
- )
|
|
|
|
|
|
|
+ ))
|
|
|
{
|
|
{
|
|
|
d->seekpos += Over;
|
|
d->seekpos += Over;
|
|
|
char buffer[1024];
|
|
char buffer[1024];
|
|
@@ -1407,7 +1513,10 @@ bool FileFd::Skip(unsigned long long Over)
|
|
|
{
|
|
{
|
|
|
unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over);
|
|
unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over);
|
|
|
if (Read(buffer, toread) == false)
|
|
if (Read(buffer, toread) == false)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Error("Unable to seek ahead %llu",Over);
|
|
return _error->Error("Unable to seek ahead %llu",Over);
|
|
|
|
|
+ }
|
|
|
Over -= toread;
|
|
Over -= toread;
|
|
|
}
|
|
}
|
|
|
return true;
|
|
return true;
|
|
@@ -1415,7 +1524,7 @@ bool FileFd::Skip(unsigned long long Over)
|
|
|
|
|
|
|
|
int res;
|
|
int res;
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
res = gzseek(d->gz,Over,SEEK_CUR);
|
|
res = gzseek(d->gz,Over,SEEK_CUR);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
@@ -1425,7 +1534,8 @@ bool FileFd::Skip(unsigned long long Over)
|
|
|
Flags |= Fail;
|
|
Flags |= Fail;
|
|
|
return _error->Error("Unable to seek ahead %llu",Over);
|
|
return _error->Error("Unable to seek ahead %llu",Over);
|
|
|
}
|
|
}
|
|
|
- d->seekpos = res;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->seekpos = res;
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -1436,7 +1546,7 @@ bool FileFd::Skip(unsigned long long Over)
|
|
|
bool FileFd::Truncate(unsigned long long To)
|
|
bool FileFd::Truncate(unsigned long long To)
|
|
|
{
|
|
{
|
|
|
#if defined HAVE_ZLIB || defined HAVE_BZ2
|
|
#if defined HAVE_ZLIB || defined HAVE_BZ2
|
|
|
- if (d->gz != NULL || d->bz2 != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
|
|
|
{
|
|
{
|
|
|
Flags |= Fail;
|
|
Flags |= Fail;
|
|
|
return _error->Error("Truncating compressed files is not implemented (%s)", FileName.c_str());
|
|
return _error->Error("Truncating compressed files is not implemented (%s)", FileName.c_str());
|
|
@@ -1460,23 +1570,27 @@ unsigned long long FileFd::Tell()
|
|
|
// seeking around, but not all users of FileFd use always Seek() and co
|
|
// seeking around, but not all users of FileFd use always Seek() and co
|
|
|
// so d->seekpos isn't always true and we can just use it as a hint if
|
|
// so d->seekpos isn't always true and we can just use it as a hint if
|
|
|
// we have nothing else, but not always as an authority…
|
|
// we have nothing else, but not always as an authority…
|
|
|
- if (d->pipe == true
|
|
|
|
|
|
|
+ if (d != NULL && (d->pipe == true
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- || d->bz2 != NULL
|
|
|
|
|
|
|
+ || d->bz2 != NULL
|
|
|
#endif
|
|
#endif
|
|
|
- )
|
|
|
|
|
|
|
+ ))
|
|
|
return d->seekpos;
|
|
return d->seekpos;
|
|
|
|
|
|
|
|
off_t Res;
|
|
off_t Res;
|
|
|
#ifdef HAVE_ZLIB
|
|
#ifdef HAVE_ZLIB
|
|
|
- if (d->gz != NULL)
|
|
|
|
|
|
|
+ if (d != NULL && d->gz != NULL)
|
|
|
Res = gztell(d->gz);
|
|
Res = gztell(d->gz);
|
|
|
else
|
|
else
|
|
|
#endif
|
|
#endif
|
|
|
Res = lseek(iFd,0,SEEK_CUR);
|
|
Res = lseek(iFd,0,SEEK_CUR);
|
|
|
if (Res == (off_t)-1)
|
|
if (Res == (off_t)-1)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
_error->Errno("lseek","Failed to determine the current file position");
|
|
_error->Errno("lseek","Failed to determine the current file position");
|
|
|
- d->seekpos = Res;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->seekpos = Res;
|
|
|
return Res;
|
|
return Res;
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
@@ -1486,17 +1600,24 @@ unsigned long long FileFd::Tell()
|
|
|
unsigned long long FileFd::FileSize()
|
|
unsigned long long FileFd::FileSize()
|
|
|
{
|
|
{
|
|
|
struct stat Buf;
|
|
struct stat Buf;
|
|
|
- if (d->pipe == false && fstat(iFd,&Buf) != 0)
|
|
|
|
|
|
|
+ if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Errno("fstat","Unable to determine the file size");
|
|
return _error->Errno("fstat","Unable to determine the file size");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// for compressor pipes st_size is undefined and at 'best' zero
|
|
// for compressor pipes st_size is undefined and at 'best' zero
|
|
|
- if (d->pipe == true || S_ISFIFO(Buf.st_mode))
|
|
|
|
|
|
|
+ if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
|
|
|
{
|
|
{
|
|
|
// we set it here, too, as we get the info here for free
|
|
// we set it here, too, as we get the info here for free
|
|
|
// in theory the Open-methods should take care of it already
|
|
// in theory the Open-methods should take care of it already
|
|
|
- d->pipe = true;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->pipe = true;
|
|
|
if (stat(FileName.c_str(), &Buf) != 0)
|
|
if (stat(FileName.c_str(), &Buf) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Errno("stat","Unable to determine the file size");
|
|
return _error->Errno("stat","Unable to determine the file size");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return Buf.st_size;
|
|
return Buf.st_size;
|
|
@@ -1511,11 +1632,11 @@ unsigned long long FileFd::Size()
|
|
|
|
|
|
|
|
// for compressor pipes st_size is undefined and at 'best' zero,
|
|
// for compressor pipes st_size is undefined and at 'best' zero,
|
|
|
// so we 'read' the content and 'seek' back - see there
|
|
// so we 'read' the content and 'seek' back - see there
|
|
|
- if (d->pipe == true
|
|
|
|
|
|
|
+ if (d != NULL && (d->pipe == true
|
|
|
#ifdef HAVE_BZ2
|
|
#ifdef HAVE_BZ2
|
|
|
- || (d->bz2 && size > 0)
|
|
|
|
|
|
|
+ || (d->bz2 && size > 0)
|
|
|
#endif
|
|
#endif
|
|
|
- )
|
|
|
|
|
|
|
+ ))
|
|
|
{
|
|
{
|
|
|
unsigned long long const oldSeek = Tell();
|
|
unsigned long long const oldSeek = Tell();
|
|
|
char ignore[1000];
|
|
char ignore[1000];
|
|
@@ -1530,7 +1651,7 @@ unsigned long long FileFd::Size()
|
|
|
// only check gzsize if we are actually a gzip file, just checking for
|
|
// only check gzsize if we are actually a gzip file, just checking for
|
|
|
// "gz" is not sufficient as uncompressed files could be opened with
|
|
// "gz" is not sufficient as uncompressed files could be opened with
|
|
|
// gzopen in "direct" mode as well
|
|
// gzopen in "direct" mode as well
|
|
|
- else if (d->gz && !gzdirect(d->gz) && size > 0)
|
|
|
|
|
|
|
+ else if (d != NULL && d->gz && !gzdirect(d->gz) && size > 0)
|
|
|
{
|
|
{
|
|
|
off_t const oldPos = lseek(iFd,0,SEEK_CUR);
|
|
off_t const oldPos = lseek(iFd,0,SEEK_CUR);
|
|
|
/* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
|
|
/* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
|
|
@@ -1538,10 +1659,16 @@ unsigned long long FileFd::Size()
|
|
|
* bits of the file */
|
|
* bits of the file */
|
|
|
// FIXME: Size for gz-files is limited by 32bit… no largefile support
|
|
// FIXME: Size for gz-files is limited by 32bit… no largefile support
|
|
|
if (lseek(iFd, -4, SEEK_END) < 0)
|
|
if (lseek(iFd, -4, SEEK_END) < 0)
|
|
|
- return _error->Errno("lseek","Unable to seek to end of gzipped file");
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
|
|
+ return _error->Errno("lseek","Unable to seek to end of gzipped file");
|
|
|
|
|
+ }
|
|
|
size = 0L;
|
|
size = 0L;
|
|
|
if (read(iFd, &size, 4) != 4)
|
|
if (read(iFd, &size, 4) != 4)
|
|
|
- return _error->Errno("read","Unable to read original size of gzipped file");
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
|
|
+ return _error->Errno("read","Unable to read original size of gzipped file");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
uint32_t tmp_size = size;
|
|
uint32_t tmp_size = size;
|
|
@@ -1551,7 +1678,10 @@ unsigned long long FileFd::Size()
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
if (lseek(iFd, oldPos, SEEK_SET) < 0)
|
|
if (lseek(iFd, oldPos, SEEK_SET) < 0)
|
|
|
- return _error->Errno("lseek","Unable to seek in gzipped file");
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
|
|
+ return _error->Errno("lseek","Unable to seek in gzipped file");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return size;
|
|
return size;
|
|
|
}
|
|
}
|
|
@@ -1566,20 +1696,23 @@ unsigned long long FileFd::Size()
|
|
|
time_t FileFd::ModificationTime()
|
|
time_t FileFd::ModificationTime()
|
|
|
{
|
|
{
|
|
|
struct stat Buf;
|
|
struct stat Buf;
|
|
|
- if (d->pipe == false && fstat(iFd,&Buf) != 0)
|
|
|
|
|
|
|
+ if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
|
|
|
{
|
|
{
|
|
|
|
|
+ Flags |= Fail;
|
|
|
_error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
|
|
_error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// for compressor pipes st_size is undefined and at 'best' zero
|
|
// for compressor pipes st_size is undefined and at 'best' zero
|
|
|
- if (d->pipe == true || S_ISFIFO(Buf.st_mode))
|
|
|
|
|
|
|
+ if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
|
|
|
{
|
|
{
|
|
|
// we set it here, too, as we get the info here for free
|
|
// we set it here, too, as we get the info here for free
|
|
|
// in theory the Open-methods should take care of it already
|
|
// in theory the Open-methods should take care of it already
|
|
|
- d->pipe = true;
|
|
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ d->pipe = true;
|
|
|
if (stat(FileName.c_str(), &Buf) != 0)
|
|
if (stat(FileName.c_str(), &Buf) != 0)
|
|
|
{
|
|
{
|
|
|
|
|
+ Flags |= Fail;
|
|
|
_error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
|
|
_error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -1599,24 +1732,18 @@ bool FileFd::Close()
|
|
|
bool Res = true;
|
|
bool Res = true;
|
|
|
if ((Flags & AutoClose) == AutoClose)
|
|
if ((Flags & AutoClose) == AutoClose)
|
|
|
{
|
|
{
|
|
|
-#ifdef HAVE_ZLIB
|
|
|
|
|
- if (d != NULL && d->gz != NULL) {
|
|
|
|
|
- int const e = gzclose(d->gz);
|
|
|
|
|
- // gzdclose() 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
|
|
|
|
|
-#ifdef HAVE_BZ2
|
|
|
|
|
- if (d != NULL && d->bz2 != NULL)
|
|
|
|
|
- BZ2_bzclose(d->bz2);
|
|
|
|
|
- else
|
|
|
|
|
-#endif
|
|
|
|
|
- if (iFd > 0 && close(iFd) != 0)
|
|
|
|
|
- Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
|
|
|
|
|
|
|
+ if ((Flags & Compressed) != Compressed && iFd > 0 && close(iFd) != 0)
|
|
|
|
|
+ Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
|
|
|
|
|
+
|
|
|
|
|
+ if (d != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ Res &= d->CloseDown(FileName);
|
|
|
|
|
+ delete d;
|
|
|
|
|
+ d = NULL;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if ((Flags & Replace) == Replace && iFd >= 0) {
|
|
|
|
|
|
|
+ if ((Flags & Replace) == Replace) {
|
|
|
if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0)
|
|
if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0)
|
|
|
Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str());
|
|
Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str());
|
|
|
|
|
|
|
@@ -1631,14 +1758,8 @@ bool FileFd::Close()
|
|
|
if (unlink(FileName.c_str()) != 0)
|
|
if (unlink(FileName.c_str()) != 0)
|
|
|
Res &= _error->WarningE("unlnk",_("Problem unlinking the file %s"), FileName.c_str());
|
|
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;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (Res == false)
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return Res;
|
|
return Res;
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
@@ -1649,7 +1770,10 @@ bool FileFd::Sync()
|
|
|
{
|
|
{
|
|
|
#ifdef _POSIX_SYNCHRONIZED_IO
|
|
#ifdef _POSIX_SYNCHRONIZED_IO
|
|
|
if (fsync(iFd) != 0)
|
|
if (fsync(iFd) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Flags |= Fail;
|
|
|
return _error->Errno("sync",_("Problem syncing the file"));
|
|
return _error->Errno("sync",_("Problem syncing the file"));
|
|
|
|
|
+ }
|
|
|
#endif
|
|
#endif
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|