return AbsPath;
}
/*}}}*/
+std::string flNormalize(std::string file) /*{{{*/
+{
+ if (file.empty())
+ return file;
+ // do some normalisation by removing // and /./ from the path
+ size_t found = string::npos;
+ while ((found = file.find("/./")) != string::npos)
+ file.replace(found, 3, "/");
+ while ((found = file.find("//")) != string::npos)
+ file.replace(found, 2, "/");
+
+ if (APT::String::Startswith(file, "/dev/null"))
+ {
+ file.erase(strlen("/dev/null"));
+ return file;
+ }
+ return file;
+}
+ /*}}}*/
// SetCloseExec - Set the close on exec flag /*{{{*/
// ---------------------------------------------------------------------
/* */
// ensure the file is owned by root and has good permissions
struct passwd const * const pw = getpwnam(user);
struct group const * const gr = getgrnam(group);
- if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0)
+ if (pw != NULL && gr != NULL && lchown(file, pw->pw_uid, gr->gr_gid) != 0)
Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file);
}
+ struct stat Buf;
+ if (lstat(file, &Buf) != 0 || S_ISLNK(Buf.st_mode))
+ return Res;
if (chmod(file, mode) != 0)
Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file);
return Res;
{
buffer.reset();
unsigned long long actualread = 0;
- if (filefd->Read(buffer.get(), buffer.buffersize_max, &actualread) == false)
+ if (filefd->Read(buffer.getend(), buffer.free(), &actualread) == false)
return nullptr;
buffer.bufferend = actualread;
if (buffer.size() == 0)
return filefd->FileFdError("Seek on file %s because it couldn't be reopened", filefd->FileName.c_str());
buffer.reset();
+ set_seekpos(0);
if (To != 0)
return filefd->Skip(To);
virtual ~FileFdPrivate() {}
};
/*}}}*/
-class APT_HIDDEN BufferedWriteFileFdPrivate : public FileFdPrivate { /*{{{*/
+class APT_HIDDEN BufferedWriteFileFdPrivate : public FileFdPrivate { /*{{{*/
protected:
FileFdPrivate *wrapped;
simple_buffer writebuffer;
explicit BufferedWriteFileFdPrivate(FileFdPrivate *Priv) :
FileFdPrivate(Priv->filefd), wrapped(Priv) {};
- virtual APT::Configuration::Compressor get_compressor() const override
+ virtual APT::Configuration::Compressor get_compressor() const APT_OVERRIDE
{
return wrapped->get_compressor();
}
- virtual void set_compressor(APT::Configuration::Compressor const &compressor) override
+ virtual void set_compressor(APT::Configuration::Compressor const &compressor) APT_OVERRIDE
{
return wrapped->set_compressor(compressor);
}
- virtual unsigned int get_openmode() const override
+ virtual unsigned int get_openmode() const APT_OVERRIDE
{
return wrapped->get_openmode();
}
- virtual void set_openmode(unsigned int openmode) override
+ virtual void set_openmode(unsigned int openmode) APT_OVERRIDE
{
return wrapped->set_openmode(openmode);
}
- virtual bool get_is_pipe() const override
+ virtual bool get_is_pipe() const APT_OVERRIDE
{
return wrapped->get_is_pipe();
}
- virtual void set_is_pipe(bool is_pipe) override
+ virtual void set_is_pipe(bool is_pipe) APT_OVERRIDE
{
FileFdPrivate::set_is_pipe(is_pipe);
wrapped->set_is_pipe(is_pipe);
}
- virtual unsigned long long get_seekpos() const override
+ virtual unsigned long long get_seekpos() const APT_OVERRIDE
{
return wrapped->get_seekpos();
}
- virtual void set_seekpos(unsigned long long seekpos) override
+ virtual void set_seekpos(unsigned long long seekpos) APT_OVERRIDE
{
return wrapped->set_seekpos(seekpos);
}
- virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+ virtual bool InternalOpen(int const iFd, unsigned int const Mode) APT_OVERRIDE
{
if (InternalFlush() == false)
return false;
return wrapped->InternalOpen(iFd, Mode);
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
if (InternalFlush() == false)
return -1;
return wrapped->InternalUnbufferedRead(To, Size);
}
- virtual bool InternalReadError() override
+ virtual bool InternalReadError() APT_OVERRIDE
{
return wrapped->InternalReadError();
}
- virtual char * InternalReadLine(char * To, unsigned long long Size) override
+ virtual char * InternalReadLine(char * To, unsigned long long Size) APT_OVERRIDE
{
if (InternalFlush() == false)
return nullptr;
return wrapped->InternalReadLine(To, Size);
}
- virtual bool InternalFlush() override
+ virtual bool InternalFlush() APT_OVERRIDE
{
while (writebuffer.empty() == false) {
auto written = wrapped->InternalWrite(writebuffer.get(),
if (written < 0 && errno == EINTR)
continue;
if (written < 0)
- return false;
+ return wrapped->InternalWriteError();
writebuffer.bufferstart += written;
}
writebuffer.reset();
return true;
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
+ // Optimisation: If the buffer is empty and we have more to write than
+ // would fit in the buffer (or equal number of bytes), write directly.
+ if (writebuffer.empty() == true && Size >= writebuffer.free())
+ return wrapped->InternalWrite(From, Size);
+
+ // Write as much into the buffer as possible and then flush if needed
auto written = writebuffer.write(From, Size);
if (writebuffer.full() && InternalFlush() == false)
return written;
}
- virtual bool InternalWriteError()
+ virtual bool InternalWriteError() APT_OVERRIDE
{
return wrapped->InternalWriteError();
}
- virtual bool InternalSeek(unsigned long long const To)
+ virtual bool InternalSeek(unsigned long long const To) APT_OVERRIDE
{
if (InternalFlush() == false)
return false;
return wrapped->InternalSeek(To);
}
- virtual bool InternalSkip(unsigned long long Over)
+ virtual bool InternalSkip(unsigned long long Over) APT_OVERRIDE
{
if (InternalFlush() == false)
return false;
return wrapped->InternalSkip(Over);
}
- virtual bool InternalTruncate(unsigned long long const Size)
+ virtual bool InternalTruncate(unsigned long long const Size) APT_OVERRIDE
{
if (InternalFlush() == false)
return false;
return wrapped->InternalTruncate(Size);
}
- virtual unsigned long long InternalTell()
+ virtual unsigned long long InternalTell() APT_OVERRIDE
{
if (InternalFlush() == false)
return -1;
return wrapped->InternalTell();
}
- virtual unsigned long long InternalSize()
+ virtual unsigned long long InternalSize() APT_OVERRIDE
{
if (InternalFlush() == false)
return -1;
return wrapped->InternalSize();
}
- virtual bool InternalClose(std::string const &FileName)
+ virtual bool InternalClose(std::string const &FileName) APT_OVERRIDE
{
return wrapped->InternalClose(FileName);
}
- virtual bool InternalAlwaysAutoClose() const
+ virtual bool InternalAlwaysAutoClose() const APT_OVERRIDE
{
return wrapped->InternalAlwaysAutoClose();
}
#ifdef HAVE_ZLIB
public:
gzFile gz;
- virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+ virtual bool InternalOpen(int const iFd, unsigned int const Mode) APT_OVERRIDE
{
if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite)
gz = gzdopen(iFd, "r+");
filefd->Flags |= FileFd::Compressed;
return gz != nullptr;
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
return gzread(gz, To, Size);
}
- virtual bool InternalReadError() override
+ virtual bool InternalReadError() APT_OVERRIDE
{
int err;
char const * const errmsg = gzerror(gz, &err);
return filefd->FileFdError("gzread: %s (%d: %s)", _("Read error"), err, errmsg);
return FileFdPrivate::InternalReadError();
}
- virtual char * InternalReadLine(char * To, unsigned long long Size) override
+ virtual char * InternalReadLine(char * To, unsigned long long Size) APT_OVERRIDE
{
return gzgets(gz, To, Size);
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
return gzwrite(gz,From,Size);
}
- virtual bool InternalWriteError() override
+ virtual bool InternalWriteError() APT_OVERRIDE
{
int err;
char const * const errmsg = gzerror(gz, &err);
return filefd->FileFdError("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
return FileFdPrivate::InternalWriteError();
}
- virtual bool InternalSeek(unsigned long long const To) override
+ virtual bool InternalSeek(unsigned long long const To) APT_OVERRIDE
{
off_t const res = gzseek(gz, To, SEEK_SET);
if (res != (off_t)To)
buffer.reset();
return true;
}
- virtual bool InternalSkip(unsigned long long Over) override
+ virtual bool InternalSkip(unsigned long long Over) APT_OVERRIDE
{
if (Over >= buffer.size())
{
seekpos = res;
return true;
}
- virtual unsigned long long InternalTell() override
+ virtual unsigned long long InternalTell() APT_OVERRIDE
{
return gztell(gz) - buffer.size();
}
- virtual unsigned long long InternalSize() override
+ virtual unsigned long long InternalSize() APT_OVERRIDE
{
unsigned long long filesize = FileFdPrivate::InternalSize();
// only check gzsize if we are actually a gzip file, just checking for
}
return size;
}
- virtual bool InternalClose(std::string const &FileName) override
+ virtual bool InternalClose(std::string const &FileName) APT_OVERRIDE
{
if (gz == nullptr)
return true;
#ifdef HAVE_BZ2
BZFILE* bz2;
public:
- virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+ virtual bool InternalOpen(int const iFd, unsigned int const Mode) APT_OVERRIDE
{
if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite)
bz2 = BZ2_bzdopen(iFd, "r+");
filefd->Flags |= FileFd::Compressed;
return bz2 != nullptr;
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
return BZ2_bzread(bz2, To, Size);
}
- virtual bool InternalReadError() override
+ virtual bool InternalReadError() APT_OVERRIDE
{
int err;
char const * const errmsg = BZ2_bzerror(bz2, &err);
return filefd->FileFdError("BZ2_bzread: %s %s (%d: %s)", filefd->FileName.c_str(), _("Read error"), err, errmsg);
return FileFdPrivate::InternalReadError();
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
return BZ2_bzwrite(bz2, (void*)From, Size);
}
- virtual bool InternalWriteError() override
+ virtual bool InternalWriteError() APT_OVERRIDE
{
int err;
char const * const errmsg = BZ2_bzerror(bz2, &err);
return filefd->FileFdError("BZ2_bzwrite: %s %s (%d: %s)", filefd->FileName.c_str(), _("Write error"), err, errmsg);
return FileFdPrivate::InternalWriteError();
}
- virtual bool InternalStream() const override { return true; }
- virtual bool InternalClose(std::string const &) override
+ virtual bool InternalStream() const APT_OVERRIDE { return true; }
+ virtual bool InternalClose(std::string const &) APT_OVERRIDE
{
if (bz2 == nullptr)
return true;
// Count of bytes that the decompressor expects to read next, or buffer size.
size_t next_to_load = APT_BUFFER_SIZE;
public:
- virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+ virtual bool InternalOpen(int const iFd, unsigned int const Mode) APT_OVERRIDE
{
if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite)
return _error->Error("lz4 only supports write or read mode");
return false;
unsigned int flags = (Mode & (FileFd::WriteOnly|FileFd::ReadOnly));
- if (backend.OpenDescriptor(iFd, flags) == false)
+ if (backend.OpenDescriptor(iFd, flags, FileFd::None, true) == false)
return false;
// Write the file header
return true;
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
/* Keep reading as long as the compressor still wants to read */
while (next_to_load) {
return 0;
}
- virtual bool InternalReadError() override
+ virtual bool InternalReadError() APT_OVERRIDE
{
char const * const errmsg = LZ4F_getErrorName(res);
return filefd->FileFdError("LZ4F: %s %s (%zu: %s)", filefd->FileName.c_str(), _("Read error"), res, errmsg);
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
unsigned long long const towrite = std::min(APT_BUFFER_SIZE, Size);
return towrite;
}
- virtual bool InternalWriteError() override
+ virtual bool InternalWriteError() APT_OVERRIDE
{
char const * const errmsg = LZ4F_getErrorName(res);
return filefd->FileFdError("LZ4F: %s %s (%zu: %s)", filefd->FileName.c_str(), _("Write error"), res, errmsg);
}
- virtual bool InternalStream() const override { return true; }
+ virtual bool InternalStream() const APT_OVERRIDE { return true; }
- virtual bool InternalFlush() override
+ virtual bool InternalFlush() APT_OVERRIDE
{
return backend.Flush();
}
- virtual bool InternalClose(std::string const &) override
+ virtual bool InternalClose(std::string const &) APT_OVERRIDE
{
/* Reset variables */
res = 0;
if (cctx != nullptr)
{
- res = LZ4F_compressEnd(cctx, lz4_buffer.buffer, lz4_buffer.buffersize_max, nullptr);
- if (LZ4F_isError(res) || backend.Write(lz4_buffer.buffer, res) == false)
- return false;
- if (!backend.Flush())
- return false;
+ if (filefd->Failed() == false)
+ {
+ res = LZ4F_compressEnd(cctx, lz4_buffer.buffer, lz4_buffer.buffersize_max, nullptr);
+ if (LZ4F_isError(res) || backend.Write(lz4_buffer.buffer, res) == false)
+ return false;
+ if (!backend.Flush())
+ return false;
+ }
if (!backend.Close())
return false;
res = LZ4F_freeDecompressionContext(dctx);
dctx = nullptr;
}
+ if (backend.IsOpen())
+ {
+ backend.Close();
+ filefd->iFd = -1;
+ }
return LZ4F_isError(res) == false;
}
#ifdef HAVE_LZMA
struct LZMAFILE {
FILE* file;
+ FileFd * const filefd;
uint8_t buffer[4096];
lzma_stream stream;
lzma_ret err;
bool eof;
bool compressing;
- LZMAFILE() : file(nullptr), eof(false), compressing(false) { buffer[0] = '\0'; }
+ LZMAFILE(FileFd * const fd) : file(nullptr), filefd(fd), eof(false), compressing(false) { buffer[0] = '\0'; }
~LZMAFILE()
{
- if (compressing == true)
+ if (compressing == true && filefd->Failed() == false)
{
size_t constexpr buffersize = sizeof(buffer)/sizeof(buffer[0]);
while(true)
return 6;
}
public:
- virtual bool InternalOpen(int const iFd, unsigned int const Mode) override
+ virtual bool InternalOpen(int const iFd, unsigned int const Mode) APT_OVERRIDE
{
if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite)
return filefd->FileFdError("ReadWrite mode is not supported for lzma/xz files %s", filefd->FileName.c_str());
if (lzma == nullptr)
- lzma = new LzmaFileFdPrivate::LZMAFILE;
+ lzma = new LzmaFileFdPrivate::LZMAFILE(filefd);
if ((Mode & FileFd::WriteOnly) == FileFd::WriteOnly)
lzma->file = fdopen(iFd, "w");
else
}
return true;
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
ssize_t Res;
if (lzma->eof == true)
}
return Res;
}
- virtual bool InternalReadError() override
+ virtual bool InternalReadError() APT_OVERRIDE
{
return filefd->FileFdError("lzma_read: %s (%d)", _("Read error"), lzma->err);
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
+ ssize_t Res;
lzma->stream.next_in = (uint8_t *)From;
lzma->stream.avail_in = Size;
lzma->stream.next_out = lzma->buffer;
size_t const n = sizeof(lzma->buffer)/sizeof(lzma->buffer[0]) - lzma->stream.avail_out;
size_t const m = (n == 0) ? 0 : fwrite(lzma->buffer, 1, n, lzma->file);
if (m != n)
- return -1;
+ {
+ Res = -1;
+ errno = 0;
+ }
else
- return Size - lzma->stream.avail_in;
+ {
+ Res = Size - lzma->stream.avail_in;
+ if (Res == 0)
+ {
+ // lzma run was okay, but produced no output…
+ Res = -1;
+ errno = EINTR;
+ }
+ }
+ return Res;
}
- virtual bool InternalWriteError() override
+ virtual bool InternalWriteError() APT_OVERRIDE
{
return filefd->FileFdError("lzma_write: %s (%d)", _("Write error"), lzma->err);
}
- virtual bool InternalStream() const override { return true; }
- virtual bool InternalClose(std::string const &) override
+ virtual bool InternalStream() const APT_OVERRIDE { return true; }
+ virtual bool InternalClose(std::string const &) APT_OVERRIDE
{
delete lzma;
lzma = nullptr;
by executing a specified binary and pipe in/out what we need */
{
public:
- virtual bool InternalOpen(int const, unsigned int const Mode) override
+ virtual bool InternalOpen(int const, unsigned int const Mode) APT_OVERRIDE
{
// collect zombies here in case we reopen
if (compressor_pid > 0)
if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite)
return filefd->FileFdError("ReadWrite mode is not supported for file %s", filefd->FileName.c_str());
+ if (compressor.Binary == "false")
+ return filefd->FileFdError("libapt has inbuilt support for the %s compression,"
+ " but was forced to ignore it in favor of an external binary – which isn't installed.", compressor.Name.c_str());
bool const Comp = (Mode & FileFd::WriteOnly) == FileFd::WriteOnly;
if (Comp == false)
return true;
}
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
return read(filefd->iFd, To, Size);
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
return write(filefd->iFd, From, Size);
}
- virtual bool InternalClose(std::string const &) override
+ virtual bool InternalClose(std::string const &) APT_OVERRIDE
{
bool Ret = true;
+ if (filefd->iFd != -1)
+ {
+ close(filefd->iFd);
+ filefd->iFd = -1;
+ }
if (compressor_pid > 0)
Ret &= ExecWait(compressor_pid, "FileFdCompressor", true);
compressor_pid = -1;
class APT_HIDDEN DirectFileFdPrivate: public FileFdPrivate /*{{{*/
{
public:
- virtual bool InternalOpen(int const, unsigned int const) override { return true; }
- virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) override
+ virtual bool InternalOpen(int const, unsigned int const) APT_OVERRIDE { return true; }
+ virtual ssize_t InternalUnbufferedRead(void * const To, unsigned long long const Size) APT_OVERRIDE
{
return read(filefd->iFd, To, Size);
}
- virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
+ virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE
{
// files opened read+write are strange and only really "supported" for direct files
if (buffer.size() != 0)
}
return write(filefd->iFd, From, Size);
}
- virtual bool InternalSeek(unsigned long long const To) override
+ virtual bool InternalSeek(unsigned long long const To) APT_OVERRIDE
{
off_t const res = lseek(filefd->iFd, To, SEEK_SET);
if (res != (off_t)To)
buffer.reset();
return true;
}
- virtual bool InternalSkip(unsigned long long Over) override
+ virtual bool InternalSkip(unsigned long long Over) APT_OVERRIDE
{
if (Over >= buffer.size())
{
seekpos = res;
return true;
}
- virtual bool InternalTruncate(unsigned long long const To) override
+ virtual bool InternalTruncate(unsigned long long const To) APT_OVERRIDE
{
if (buffer.size() != 0)
{
return filefd->FileFdError("Unable to truncate to %llu",To);
return true;
}
- virtual unsigned long long InternalTell() override
+ virtual unsigned long long InternalTell() APT_OVERRIDE
{
return lseek(filefd->iFd,0,SEEK_CUR) - buffer.size();
}
- virtual unsigned long long InternalSize() override
+ virtual unsigned long long InternalSize() APT_OVERRIDE
{
return filefd->FileSize();
}
- virtual bool InternalClose(std::string const &) override { return true; }
- virtual bool InternalAlwaysAutoClose() const override { return false; }
+ virtual bool InternalClose(std::string const &) APT_OVERRIDE { return true; }
+ virtual bool InternalAlwaysAutoClose() const APT_OVERRIDE { return false; }
explicit DirectFileFdPrivate(FileFd * const filefd) : FileFdPrivate(filefd) {}
virtual ~DirectFileFdPrivate() { InternalClose(""); }
while (Res > 0 && Size > 0)
{
Res = d->InternalWrite(From, Size);
- if (Res < 0 && errno == EINTR)
- continue;
+
if (Res < 0)
+ {
+ if (errno == EINTR)
+ {
+ // trick the while-loop into running again
+ Res = 1;
+ errno = 0;
+ continue;
+ }
return d->InternalWriteError();
+ }
From = (char const *)From + Res;
Size -= Res;
/* */
bool FileFd::Close()
{
- if (Flush() == false)
+ if (Failed() == false && Flush() == false)
return false;
if (iFd == -1)
return true;
}
if ((Flags & Replace) == Replace) {
- if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0)
+ if (Failed() == false && 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());
FileName = TemporaryFileName; // for the unlink() below.