X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/ff477ee133fb448622cc86f658f1a9b23577e413..e7c82918f3abfb49d794bbe697f8721f25333b77:/apt-pkg/contrib/fileutl.cc diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index c8e685a5a..f24df65fc 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -81,6 +81,31 @@ class FileFdPrivate { FileFdPrivate() : gz(NULL), bz2(NULL), compressed_fd(-1), compressor_pid(-1), pipe(false), 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 /*{{{*/ @@ -159,7 +184,8 @@ bool RunScripts(const char *Cnf) /* The caller is expected to set things so that failure causes erasure */ bool CopyFile(FileFd &From,FileFd &To) { - if (From.IsOpen() == false || To.IsOpen() == false) + if (From.IsOpen() == false || To.IsOpen() == false || + From.Failed() == true || To.Failed() == true) return false; // Buffered copy between fds @@ -218,17 +244,20 @@ int GetLock(string File,bool Errors) fl.l_len = 0; if (fcntl(FD,F_SETLK,&fl) == -1) { + // always close to not leak resources + int Tmp = errno; + close(FD); + errno = Tmp; + if (errno == ENOLCK) { _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str()); return dup(0); // Need something for the caller to close - } + } + if (Errors == true) _error->Errno("open",_("Could not get lock %s"),File.c_str()); - int Tmp = errno; - close(FD); - errno = Tmp; return -1; } @@ -362,7 +391,7 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c std::vector List; - if (DirectoryExists(Dir.c_str()) == false) + if (DirectoryExists(Dir) == false) { _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str()); return List; @@ -388,14 +417,14 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c if (Ent->d_type != DT_REG) #endif { - if (RealFileExists(File.c_str()) == false) + if (RealFileExists(File) == false) { // do not show ignoration warnings for directories if ( #ifdef _DIRENT_HAVE_D_TYPE Ent->d_type == DT_DIR || #endif - DirectoryExists(File.c_str()) == true) + DirectoryExists(File) == true) continue; if (SilentIgnore.Match(Ent->d_name) == false) _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str()); @@ -476,7 +505,7 @@ std::vector GetListOfFilesInDir(string const &Dir, bool SortList) std::vector List; - if (DirectoryExists(Dir.c_str()) == false) + if (DirectoryExists(Dir) == false) { _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str()); return List; @@ -501,7 +530,7 @@ std::vector GetListOfFilesInDir(string const &Dir, bool SortList) if (Ent->d_type != DT_REG) #endif { - if (RealFileExists(File.c_str()) == false) + if (RealFileExists(File) == false) { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → it is not a real file" << std::endl; @@ -836,7 +865,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, 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()); + return FileFdError("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str()); std::vector const compressors = APT::Configuration::getCompressors(); std::vector::const_iterator compressor = compressors.begin(); @@ -889,17 +918,17 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, case Auto: case Extension: // Unreachable - return _error->Error("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str()); + return FileFdError("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()); + return FileFdError("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str()); } if (compressor == compressors.end()) - return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str()); + return FileFdError("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) @@ -908,9 +937,9 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co 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()); + return FileFdError("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()); + return FileFdError("No openmode provided in FileFd::Open for %s", FileName.c_str()); if ((Mode & Atomic) == Atomic) { @@ -956,7 +985,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co close (iFd); iFd = -1; } - return _error->Errno("open",_("Could not open file %s"), FileName.c_str()); + return FileFdErrno("open",_("Could not open file %s"), FileName.c_str()); } SetCloseExec(iFd,true); @@ -985,27 +1014,55 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compre 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); + if (AutoClose == true && Fd != -1) + close(Fd); + return FileFdError("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()); - + { + if (AutoClose == true && Fd != -1) + close(Fd); + return FileFdError("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(); 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 = ""; - if (OpenInternDescriptor(Mode, compressor) == false) + if (Fd == -1 || OpenInternDescriptor(Mode, compressor) == false) { - if (AutoClose) + if (iFd != -1 && ( +#ifdef HAVE_ZLIB + compressor.Name == "gzip" || +#endif +#ifdef HAVE_BZ2 + compressor.Name == "bzip2" || +#endif + AutoClose == true)) + { close (iFd); - return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd); + iFd = -1; + } + return FileFdError(_("Could not open file descriptor %d"), Fd); } return true; } @@ -1067,10 +1124,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C ExecWait(d->compressor_pid, "FileFdCompressor", true); if ((Mode & ReadWrite) == ReadWrite) - { - Flags |= Fail; - return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str()); - } + return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str()); bool const Comp = (Mode & WriteOnly) == WriteOnly; if (Comp == false) @@ -1093,10 +1147,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C // Create a data pipe int Pipe[2] = {-1,-1}; if (pipe(Pipe) != 0) - { - Flags |= Fail; - return _error->Errno("pipe",_("Failed to create subprocess IPC")); - } + return FileFdErrno("pipe",_("Failed to create subprocess IPC")); for (int J = 0; J != 2; J++) SetCloseExec(Pipe[J],true); @@ -1158,8 +1209,6 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C close(Pipe[0]); else close(Pipe[1]); - if ((Comp == true || FileName.empty() == true) && d->compressed_fd != -1) - close(d->compressed_fd); return true; } @@ -1171,6 +1220,10 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C FileFd::~FileFd() { Close(); + if (d != NULL) + d->CloseDown(FileName); + delete d; + d = NULL; } /*}}}*/ // FileFd::Read - Read a bit of the file /*{{{*/ @@ -1202,14 +1255,13 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) { if (errno == EINTR) continue; - Flags |= Fail; #ifdef HAVE_ZLIB if (d != NULL && d->gz != NULL) { int err; char const * const errmsg = gzerror(d->gz, &err); if (err != Z_ERRNO) - return _error->Error("gzread: %s (%d: %s)", _("Read error"), err, errmsg); + return FileFdError("gzread: %s (%d: %s)", _("Read error"), err, errmsg); } #endif #ifdef HAVE_BZ2 @@ -1218,10 +1270,10 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) int err; char const * const errmsg = BZ2_bzerror(d->bz2, &err); if (err != BZ_IO_ERROR) - return _error->Error("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg); + return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg); } #endif - return _error->Errno("read",_("Read error")); + return FileFdErrno("read",_("Read error")); } To = (char *)To + Res; @@ -1242,9 +1294,8 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) Flags |= HitEof; return true; } - - Flags |= Fail; - return _error->Error(_("read, still have %llu to read but none left"), Size); + + return FileFdError(_("read, still have %llu to read but none left"), Size); } /*}}}*/ // FileFd::ReadLine - Read a complete line from the file /*{{{*/ @@ -1300,14 +1351,13 @@ bool FileFd::Write(const void *From,unsigned long long Size) continue; if (Res < 0) { - Flags |= Fail; #ifdef HAVE_ZLIB if (d != NULL && d->gz != NULL) { int err; char const * const errmsg = gzerror(d->gz, &err); if (err != Z_ERRNO) - return _error->Error("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg); + return FileFdError("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg); } #endif #ifdef HAVE_BZ2 @@ -1316,10 +1366,10 @@ bool FileFd::Write(const void *From,unsigned long long Size) int err; char const * const errmsg = BZ2_bzerror(d->bz2, &err); if (err != BZ_IO_ERROR) - return _error->Error("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg); + return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg); } #endif - return _error->Errno("write",_("Write error")); + return FileFdErrno("write",_("Write error")); } From = (char *)From + Res; @@ -1331,9 +1381,8 @@ bool FileFd::Write(const void *From,unsigned long long Size) if (Size == 0) return true; - - Flags |= Fail; - return _error->Error(_("write, still have %llu to write but couldn't"), Size); + + return FileFdError(_("write, still have %llu to write but couldn't"), Size); } bool FileFd::Write(int Fd, const void *From, unsigned long long Size) { @@ -1377,13 +1426,13 @@ bool FileFd::Seek(unsigned long long To) return Skip(To - seekpos); if ((d->openmode & ReadOnly) != ReadOnly) - { - Flags |= Fail; - return _error->Error("Reopen is only implemented for read-only files!"); - } + return FileFdError("Reopen is only implemented for read-only files!"); #ifdef HAVE_BZ2 - if (d->bz2 != NULL) - BZ2_bzclose(d->bz2); + if (d->bz2 != NULL) + { + BZ2_bzclose(d->bz2); + d->bz2 = NULL; + } #endif if (iFd != -1) close(iFd); @@ -1397,18 +1446,12 @@ bool FileFd::Seek(unsigned long long To) if (d->compressed_fd > 0) if (lseek(d->compressed_fd, 0, SEEK_SET) != 0) iFd = d->compressed_fd; - if (iFd <= 0) - { - Flags |= Fail; - return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!"); - } + if (iFd < 0) + return FileFdError("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!"); } 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 FileFdError("Seek on file %s because it couldn't be reopened", FileName.c_str()); if (To != 0) return Skip(To); @@ -1424,10 +1467,7 @@ bool FileFd::Seek(unsigned long long To) #endif res = lseek(iFd,To,SEEK_SET); if (res != (signed)To) - { - Flags |= Fail; - return _error->Error("Unable to seek to %llu", To); - } + return FileFdError("Unable to seek to %llu", To); if (d != NULL) d->seekpos = To; @@ -1451,10 +1491,7 @@ bool FileFd::Skip(unsigned long long Over) { unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over); if (Read(buffer, toread) == false) - { - Flags |= Fail; - return _error->Error("Unable to seek ahead %llu",Over); - } + return FileFdError("Unable to seek ahead %llu",Over); Over -= toread; } return true; @@ -1468,10 +1505,7 @@ bool FileFd::Skip(unsigned long long Over) #endif res = lseek(iFd,Over,SEEK_CUR); if (res < 0) - { - Flags |= Fail; - return _error->Error("Unable to seek ahead %llu",Over); - } + return FileFdError("Unable to seek ahead %llu",Over); if (d != NULL) d->seekpos = res; @@ -1485,17 +1519,11 @@ bool FileFd::Truncate(unsigned long long To) { #if defined HAVE_ZLIB || defined HAVE_BZ2 if (d != NULL && (d->gz != NULL || d->bz2 != NULL)) - { - Flags |= Fail; - return _error->Error("Truncating compressed files is not implemented (%s)", FileName.c_str()); - } + return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str()); #endif if (ftruncate(iFd,To) != 0) - { - Flags |= Fail; - return _error->Error("Unable to truncate to %llu",To); - } - + return FileFdError("Unable to truncate to %llu",To); + return true; } /*}}}*/ @@ -1523,10 +1551,7 @@ unsigned long long FileFd::Tell() #endif Res = lseek(iFd,0,SEEK_CUR); if (Res == (off_t)-1) - { - Flags |= Fail; - _error->Errno("lseek","Failed to determine the current file position"); - } + FileFdErrno("lseek","Failed to determine the current file position"); if (d != NULL) d->seekpos = Res; return Res; @@ -1539,10 +1564,7 @@ unsigned long long FileFd::FileSize() { struct stat Buf; if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0) - { - Flags |= Fail; - return _error->Errno("fstat","Unable to determine the file size"); - } + return FileFdErrno("fstat","Unable to determine the file size"); // for compressor pipes st_size is undefined and at 'best' zero if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode)) @@ -1552,10 +1574,7 @@ unsigned long long FileFd::FileSize() if (d != NULL) d->pipe = true; if (stat(FileName.c_str(), &Buf) != 0) - { - Flags |= Fail; - return _error->Errno("stat","Unable to determine the file size"); - } + return FileFdErrno("stat","Unable to determine the file size"); } return Buf.st_size; @@ -1580,7 +1599,11 @@ unsigned long long FileFd::Size() char ignore[1000]; unsigned long long read = 0; do { - Read(ignore, sizeof(ignore), &read); + if (Read(ignore, sizeof(ignore), &read) == false) + { + Seek(oldSeek); + return 0; + } } while(read != 0); size = Tell(); Seek(oldSeek); @@ -1598,14 +1621,14 @@ unsigned long long FileFd::Size() // FIXME: Size for gz-files is limited by 32bit… no largefile support if (lseek(iFd, -4, SEEK_END) < 0) { - Flags |= Fail; - return _error->Errno("lseek","Unable to seek to end of gzipped file"); + FileFdErrno("lseek","Unable to seek to end of gzipped file"); + return 0; } - size = 0L; + size = 0; if (read(iFd, &size, 4) != 4) { - Flags |= Fail; - return _error->Errno("read","Unable to read original size of gzipped file"); + FileFdErrno("read","Unable to read original size of gzipped file"); + return 0; } #ifdef WORDS_BIGENDIAN @@ -1617,8 +1640,8 @@ unsigned long long FileFd::Size() if (lseek(iFd, oldPos, SEEK_SET) < 0) { - Flags |= Fail; - return _error->Errno("lseek","Unable to seek in gzipped file"); + FileFdErrno("lseek","Unable to seek in gzipped file"); + return 0; } return size; @@ -1636,8 +1659,7 @@ time_t FileFd::ModificationTime() struct stat Buf; 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()); + FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); return 0; } @@ -1650,8 +1672,7 @@ time_t FileFd::ModificationTime() d->pipe = true; if (stat(FileName.c_str(), &Buf) != 0) { - Flags |= Fail; - _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); + FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); return 0; } } @@ -1670,24 +1691,18 @@ bool FileFd::Close() bool Res = true; 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) Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str()); @@ -1702,14 +1717,6 @@ bool FileFd::Close() 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; - } - if (Res == false) Flags |= Fail; return Res; @@ -1720,14 +1727,41 @@ bool FileFd::Close() /* */ bool FileFd::Sync() { -#ifdef _POSIX_SYNCHRONIZED_IO if (fsync(iFd) != 0) + return FileFdErrno("sync",_("Problem syncing the file")); + return true; +} + /*}}}*/ +// FileFd::FileFdErrno - set Fail and call _error->Errno *{{{*/ +bool FileFd::FileFdErrno(const char *Function, const char *Description,...) +{ + Flags |= Fail; + va_list args; + size_t msgSize = 400; + int const errsv = errno; + while (true) { - Flags |= Fail; - return _error->Errno("sync",_("Problem syncing the file")); + va_start(args,Description); + if (_error->InsertErrno(GlobalError::ERROR, Function, Description, args, errsv, msgSize) == false) + break; + va_end(args); } -#endif - return true; + return false; +} + /*}}}*/ +// FileFd::FileFdError - set Fail and call _error->Error *{{{*/ +bool FileFd::FileFdError(const char *Description,...) { + Flags |= Fail; + va_list args; + size_t msgSize = 400; + while (true) + { + va_start(args,Description); + if (_error->Insert(GlobalError::ERROR, Description, args, msgSize) == false) + break; + va_end(args); + } + return false; } /*}}}*/