summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/cdromutl.cc31
-rw-r--r--apt-pkg/contrib/cmndline.cc3
-rw-r--r--apt-pkg/contrib/cmndline.h1
-rw-r--r--apt-pkg/contrib/configuration.cc17
-rw-r--r--apt-pkg/contrib/configuration.h16
-rw-r--r--apt-pkg/contrib/fileutl.cc260
-rw-r--r--apt-pkg/contrib/fileutl.h46
-rw-r--r--apt-pkg/contrib/gpgv.cc63
-rw-r--r--apt-pkg/contrib/hashes.cc156
-rw-r--r--apt-pkg/contrib/hashes.h95
-rw-r--r--apt-pkg/contrib/macros.h21
-rw-r--r--apt-pkg/contrib/netrc.cc12
-rw-r--r--apt-pkg/contrib/netrc.h4
-rw-r--r--apt-pkg/contrib/sha2_internal.cc9
-rw-r--r--apt-pkg/contrib/strutl.cc288
-rw-r--r--apt-pkg/contrib/strutl.h6
16 files changed, 737 insertions, 291 deletions
diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc
index 936e377fb..6eb917457 100644
--- a/apt-pkg/contrib/cdromutl.cc
+++ b/apt-pkg/contrib/cdromutl.cc
@@ -207,7 +207,6 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
/* Run over the directory, we assume that the reader order will never
change as the media is read-only. In theory if the kernel did
some sort of wacked caching this might not be true.. */
- char S[300];
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
{
// Skip some files..
@@ -215,30 +214,32 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
strcmp(Dir->d_name,"..") == 0)
continue;
+ std::string S;
if (Version <= 1)
{
- sprintf(S,"%lu",(unsigned long)Dir->d_ino);
+ strprintf(S, "%lu", (unsigned long)Dir->d_ino);
}
else
{
struct stat Buf;
if (stat(Dir->d_name,&Buf) != 0)
continue;
- sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
+ strprintf(S, "%lu", (unsigned long)Buf.st_mtime);
}
-
- Hash.Add(S);
+
+ Hash.Add(S.c_str());
Hash.Add(Dir->d_name);
};
-
+
if (chdir(StartDir.c_str()) != 0) {
_error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str());
closedir(D);
return false;
}
closedir(D);
-
+
// Some stats from the fsys
+ std::string S;
if (_config->FindB("Debug::identcdrom",false) == false)
{
struct statvfs Buf;
@@ -248,19 +249,19 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
// We use a kilobyte block size to advoid overflow
if (writable_media)
{
- sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)));
+ strprintf(S, "%lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)));
} else {
- sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
- (long)(Buf.f_bfree*(Buf.f_bsize/1024)));
+ strprintf(S, "%lu %lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)),
+ (unsigned long)(Buf.f_bfree*(Buf.f_bsize/1024)));
}
- Hash.Add(S);
- sprintf(S,"-%u",Version);
+ Hash.Add(S.c_str());
+ strprintf(S, "-%u", Version);
}
else
- sprintf(S,"-%u.debug",Version);
-
+ strprintf(S, "-%u.debug", Version);
+
Res = Hash.Result().Value() + S;
- return true;
+ return true;
}
/*}}}*/
// FindMountPointForDevice - Find mountpoint for the given device /*{{{*/
diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc
index 93c1f4664..ff8b09ebc 100644
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -34,6 +34,9 @@ CommandLine::CommandLine(Args *AList,Configuration *Conf) : ArgList(AList),
Conf(Conf), FileList(0)
{
}
+CommandLine::CommandLine() : ArgList(NULL), Conf(NULL), FileList(0)
+{
+}
/*}}}*/
// CommandLine::~CommandLine - Destructor /*{{{*/
// ---------------------------------------------------------------------
diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h
index 143df58b2..58cbaa8c3 100644
--- a/apt-pkg/contrib/cmndline.h
+++ b/apt-pkg/contrib/cmndline.h
@@ -91,6 +91,7 @@ class CommandLine
static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt,
char const *ConfName, unsigned long Flags) APT_CONST;
+ CommandLine();
CommandLine(Args *AList,Configuration *Conf);
~CommandLine();
};
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 00f6ad0f9..42e35d32a 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -253,8 +253,11 @@ string Configuration::FindDir(const char *Name,const char *Default) const
// Configuration::FindVector - Find a vector of values /*{{{*/
// ---------------------------------------------------------------------
/* Returns a vector of config values under the given item */
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
-vector<string> Configuration::FindVector(const char *Name) const { return FindVector(Name, ""); }
+#if APT_PKG_ABI < 413
+vector<string> Configuration::FindVector(const char *Name) const
+{
+ return FindVector(Name, "");
+}
#endif
vector<string> Configuration::FindVector(const char *Name, std::string const &Default) const
{
@@ -626,19 +629,19 @@ string Configuration::Item::FullTag(const Item *Stop) const
tag/value. AsSectional enables Sectional parsing.*/
bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectional,
unsigned const &Depth)
-{
+{
// Open the stream for reading
- ifstream F(FName.c_str(),ios::in);
- if (!F != 0)
+ ifstream F(FName.c_str(),ios::in);
+ if (F.fail() == true)
return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str());
string LineBuffer;
string Stack[100];
unsigned int StackPos = 0;
-
+
// Parser state
string ParentTag;
-
+
int CurLine = 0;
bool InComment = false;
while (F.eof() == false)
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index c256139f4..8d7d51037 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -34,6 +34,8 @@
#include <vector>
#include <iostream>
+#include <apt-pkg/macros.h>
+
#ifndef APT_8_CLEANER_HEADERS
using std::string;
#endif
@@ -59,7 +61,7 @@ class Configuration
Item *Root;
bool ToFree;
-
+
Item *Lookup(Item *Head,const char *S,unsigned long const &Len,bool const &Create);
Item *Lookup(const char *Name,const bool &Create);
inline const Item *Lookup(const char *Name) const
@@ -82,14 +84,16 @@ class Configuration
*
* \param Name of the parent node
* \param Default list of values separated by commas */
+#if APT_PKG_ABI >= 413
+ std::vector<std::string> FindVector(const char *Name, std::string const &Default = "") const;
+ std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); };
+#else
std::vector<std::string> FindVector(const char *Name, std::string const &Default) const;
std::vector<std::string> FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); };
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
- std::vector<std::string> FindVector(const char *Name) const { return FindVector(Name, ""); };
-#else
std::vector<std::string> FindVector(const char *Name) const;
-#endif
std::vector<std::string> FindVector(std::string const &Name) const { return FindVector(Name.c_str(), ""); };
+#endif
+
int FindI(const char *Name,int const &Default = 0) const;
int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);};
bool FindB(const char *Name,bool const &Default = false) const;
@@ -129,7 +133,7 @@ class Configuration
class MatchAgainstConfig
{
std::vector<regex_t *> patterns;
- void clearPatterns();
+ APT_HIDDEN void clearPatterns();
public:
MatchAgainstConfig(char const * Config);
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 1e6d96fe9..8ec868ec0 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -47,6 +47,8 @@
#include <signal.h>
#include <errno.h>
#include <glob.h>
+#include <pwd.h>
+#include <grp.h>
#include <set>
#include <algorithm>
@@ -63,6 +65,10 @@
#include <endian.h>
#include <stdint.h>
+#if __gnu_linux__
+#include <sys/prctl.h>
+#endif
+
#include <apti18n.h>
/*}}}*/
@@ -656,6 +662,22 @@ string flCombine(string Dir,string File)
return Dir + '/' + File;
}
/*}}}*/
+// flAbsPath - Return the absolute path of the filename /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string flAbsPath(string File)
+{
+ char *p = realpath(File.c_str(), NULL);
+ if (p == NULL)
+ {
+ _error->Errno("realpath", "flAbsPath failed");
+ return "";
+ }
+ std::string AbsPath(p);
+ free(p);
+ return AbsPath;
+}
+ /*}}}*/
// SetCloseExec - Set the close on exec flag /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -836,6 +858,42 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
return true;
}
/*}}}*/
+// 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;
+}
+ /*}}}*/
+// ChangeOwnerAndPermissionOfFile - set file attributes to requested values /*{{{*/
+bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode)
+{
+ if (strcmp(file, "/dev/null") == 0)
+ return true;
+ bool Res = true;
+ if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it
+ {
+ // 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)
+ Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file);
+ }
+ if (chmod(file, mode) != 0)
+ Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file);
+ return Res;
+}
+ /*}}}*/
class FileFdPrivate { /*{{{*/
public:
@@ -854,7 +912,7 @@ class FileFdPrivate { /*{{{*/
bool eof;
bool compressing;
- LZMAFILE() : file(NULL), eof(false), compressing(false) {}
+ LZMAFILE() : file(NULL), eof(false), compressing(false) { buffer[0] = '\0'; }
~LZMAFILE() {
if (compressing == true)
{
@@ -1483,7 +1541,7 @@ 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 FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
+ return FileFdError("BZ2_bzread: %s %s (%d: %s)", FileName.c_str(), _("Read error"), err, errmsg);
}
#endif
#ifdef HAVE_LZMA
@@ -1914,7 +1972,6 @@ bool FileFd::Close()
{
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);
@@ -1994,10 +2051,7 @@ APT_DEPRECATED gzFile FileFd::gzFd() {
#endif
}
-
-// Glob - wrapper around "glob()" /*{{{*/
-// ---------------------------------------------------------------------
-/* */
+// Glob - wrapper around "glob()" /*{{{*/
std::vector<std::string> Glob(std::string const &pattern, int flags)
{
std::vector<std::string> result;
@@ -2023,8 +2077,7 @@ std::vector<std::string> Glob(std::string const &pattern, int flags)
return result;
}
/*}}}*/
-
-std::string GetTempDir()
+std::string GetTempDir() /*{{{*/
{
const char *tmpdir = getenv("TMPDIR");
@@ -2033,21 +2086,202 @@ std::string GetTempDir()
tmpdir = P_tmpdir;
#endif
- // check that tmpdir is set and exists
struct stat st;
- if (!tmpdir || strlen(tmpdir) == 0 || stat(tmpdir, &st) != 0)
+ if (!tmpdir || strlen(tmpdir) == 0 || // tmpdir is set
+ stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0 || // exists and is directory
+ access(tmpdir, R_OK | W_OK | X_OK) != 0 // current user has rwx access to directory
+ )
tmpdir = "/tmp";
return string(tmpdir);
}
+ /*}}}*/
+FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink) /*{{{*/
+{
+ char fn[512];
+ FileFd *Fd = new FileFd();
+
+ std::string tempdir = GetTempDir();
+ snprintf(fn, sizeof(fn), "%s/%s.XXXXXX",
+ tempdir.c_str(), Prefix.c_str());
+ int fd = mkstemp(fn);
+ if(ImmediateUnlink)
+ unlink(fn);
+ if (fd < 0)
+ {
+ _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn);
+ return NULL;
+ }
+ if (!Fd->OpenDescriptor(fd, FileFd::WriteOnly, FileFd::None, true))
+ {
+ _error->Errno("GetTempFile",_("Unable to write to %s"),fn);
+ return NULL;
+ }
-bool Rename(std::string From, std::string To)
+ return Fd;
+}
+ /*}}}*/
+bool Rename(std::string From, std::string To) /*{{{*/
{
if (rename(From.c_str(),To.c_str()) != 0)
{
_error->Error(_("rename failed, %s (%s -> %s)."),strerror(errno),
From.c_str(),To.c_str());
return false;
- }
+ }
return true;
}
+ /*}}}*/
+bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/*{{{*/
+{
+ int fd;
+ if (Mode != FileFd::ReadOnly && Mode != FileFd::WriteOnly)
+ return _error->Error("Popen supports ReadOnly (x)or WriteOnly mode only");
+
+ int Pipe[2] = {-1, -1};
+ if(pipe(Pipe) != 0)
+ return _error->Errno("pipe", _("Failed to create subprocess IPC"));
+
+ std::set<int> keep_fds;
+ keep_fds.insert(Pipe[0]);
+ keep_fds.insert(Pipe[1]);
+ Child = ExecFork(keep_fds);
+ if(Child < 0)
+ return _error->Errno("fork", "Failed to fork");
+ if(Child == 0)
+ {
+ if(Mode == FileFd::ReadOnly)
+ {
+ close(Pipe[0]);
+ fd = Pipe[1];
+ }
+ else if(Mode == FileFd::WriteOnly)
+ {
+ close(Pipe[1]);
+ fd = Pipe[0];
+ }
+
+ if(Mode == FileFd::ReadOnly)
+ {
+ dup2(fd, 1);
+ dup2(fd, 2);
+ } else if(Mode == FileFd::WriteOnly)
+ dup2(fd, 0);
+
+ execv(Args[0], (char**)Args);
+ _exit(100);
+ }
+ if(Mode == FileFd::ReadOnly)
+ {
+ close(Pipe[1]);
+ fd = Pipe[0];
+ } else if(Mode == FileFd::WriteOnly)
+ {
+ close(Pipe[0]);
+ fd = Pipe[1];
+ }
+ Fd.OpenDescriptor(fd, Mode, FileFd::None, true);
+
+ return true;
+}
+ /*}}}*/
+bool DropPrivileges() /*{{{*/
+{
+ if(_config->FindB("Debug::NoDropPrivs", false) == true)
+ return true;
+
+#if __gnu_linux__
+#if defined(PR_SET_NO_NEW_PRIVS) && ( PR_SET_NO_NEW_PRIVS != 38 )
+#error "PR_SET_NO_NEW_PRIVS is defined, but with a different value than expected!"
+#endif
+ // see prctl(2), needs linux3.5 at runtime - magic constant to avoid it at buildtime
+ int ret = prctl(38, 1, 0, 0, 0);
+ // ignore EINVAL - kernel is too old to understand the option
+ if(ret < 0 && errno != EINVAL)
+ _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
+#endif
+
+ // empty setting disables privilege dropping - this also ensures
+ // backward compatibility, see bug #764506
+ const std::string toUser = _config->Find("APT::Sandbox::User");
+ if (toUser.empty())
+ return true;
+
+ // uid will be 0 in the end, but gid might be different anyway
+ uid_t const old_uid = getuid();
+ gid_t const old_gid = getgid();
+
+ if (old_uid != 0)
+ return true;
+
+ struct passwd *pw = getpwnam(toUser.c_str());
+ if (pw == NULL)
+ return _error->Error("No user %s, can not drop rights", toUser.c_str());
+
+ // Do not change the order here, it might break things
+ if (setgroups(1, &pw->pw_gid))
+ return _error->Errno("setgroups", "Failed to setgroups");
+
+ if (setegid(pw->pw_gid) != 0)
+ return _error->Errno("setegid", "Failed to setegid");
+
+ if (setgid(pw->pw_gid) != 0)
+ return _error->Errno("setgid", "Failed to setgid");
+
+ if (setuid(pw->pw_uid) != 0)
+ return _error->Errno("setuid", "Failed to setuid");
+
+ // the seteuid() is probably uneeded (at least thats what the linux
+ // man-page says about setuid(2)) but we cargo culted it anyway
+ if (seteuid(pw->pw_uid) != 0)
+ return _error->Errno("seteuid", "Failed to seteuid");
+
+ // Verify that the user has only a single group, and the correct one
+ gid_t groups[1];
+ if (getgroups(1, groups) != 1)
+ return _error->Errno("getgroups", "Could not get new groups");
+ if (groups[0] != pw->pw_gid)
+ return _error->Error("Could not switch group");
+
+ // Verify that gid, egid, uid, and euid changed
+ if (getgid() != pw->pw_gid)
+ return _error->Error("Could not switch group");
+ if (getegid() != pw->pw_gid)
+ return _error->Error("Could not switch effective group");
+ if (getuid() != pw->pw_uid)
+ return _error->Error("Could not switch user");
+ if (geteuid() != pw->pw_uid)
+ return _error->Error("Could not switch effective user");
+
+#ifdef HAVE_GETRESUID
+ // verify that the saved set-user-id was changed as well
+ uid_t ruid = 0;
+ uid_t euid = 0;
+ uid_t suid = 0;
+ if (getresuid(&ruid, &euid, &suid))
+ return _error->Errno("getresuid", "Could not get saved set-user-ID");
+ if (suid != pw->pw_uid)
+ return _error->Error("Could not switch saved set-user-ID");
+#endif
+
+#ifdef HAVE_GETRESGID
+ // verify that the saved set-group-id was changed as well
+ gid_t rgid = 0;
+ gid_t egid = 0;
+ gid_t sgid = 0;
+ if (getresgid(&rgid, &egid, &sgid))
+ return _error->Errno("getresuid", "Could not get saved set-group-ID");
+ if (sgid != pw->pw_gid)
+ return _error->Error("Could not switch saved set-group-ID");
+#endif
+
+ // Check that uid and gid changes do not work anymore
+ if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1))
+ return _error->Error("Could restore a gid to root, privilege dropping did not work");
+
+ if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
+ return _error->Error("Could restore a uid to root, privilege dropping did not work");
+
+ return true;
+}
+ /*}}}*/
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 667057067..97cb05c56 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -170,6 +170,8 @@ time_t GetModificationTime(std::string const &Path);
bool Rename(std::string From, std::string To);
std::string GetTempDir();
+FileFd* GetTempFile(std::string const &Prefix = "",
+ bool ImmediateUnlink = true);
/** \brief Ensure the existence of the given Path
*
@@ -193,6 +195,34 @@ pid_t ExecFork(std::set<int> keep_fds);
void MergeKeepFdsFromConfiguration(std::set<int> &keep_fds);
bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
+// check if the given file starts with a PGP cleartext signature
+bool StartsWithGPGClearTextSignature(std::string const &FileName);
+
+/** change file attributes to requested known good values
+ *
+ * The method skips the user:group setting if not root.
+ *
+ * @param requester is printed as functionname in error cases
+ * @param file is the file to be modified
+ * @param user is the (new) owner of the file, e.g. _apt
+ * @param group is the (new) group owning the file, e.g. root
+ * @param mode is the access mode of the file, e.g. 0644
+ */
+bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode);
+
+/**
+ * \brief Drop privileges
+ *
+ * Drop the privileges to the user _apt (or the one specified in
+ * APT::Sandbox::User). This does not set the supplementary group
+ * ids up correctly, it only uses the default group. Also prevent
+ * the process from gaining any new privileges afterwards, at least
+ * on Linux.
+ *
+ * \return true on success, false on failure with _error set
+ */
+bool DropPrivileges();
+
// File string manipulators
std::string flNotDir(std::string File);
std::string flNotFile(std::string File);
@@ -200,7 +230,23 @@ std::string flNoLink(std::string File);
std::string flExtension(std::string File);
std::string flCombine(std::string Dir,std::string File);
+/** \brief Takes a file path and returns the absolute path
+ */
+std::string flAbsPath(std::string File);
+
// simple c++ glob
std::vector<std::string> Glob(std::string const &pattern, int flags=0);
+/** \brief Popen() implementation that execv() instead of using a shell
+ *
+ * \param Args the execv style command to run
+ * \param FileFd is a referenz to the FileFd to use for input or output
+ * \param Child a reference to the integer that stores the child pid
+ * Note that you must call ExecWait() or similar to cleanup
+ * \param Mode is either FileFd::ReadOnly or FileFd::WriteOnly
+ * \return true on success, false on failure with _error set
+ */
+bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode);
+
+
#endif
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index f24dd9640..9d798cca9 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -32,50 +32,30 @@ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/
/*}}}*/
// ExecGPGV - returns the command needed for verify /*{{{*/
// ---------------------------------------------------------------------
-/* Generating the commandline for calling gpgv is somehow complicated as
+/* Generating the commandline for calling gpg is somehow complicated as
we need to add multiple keyrings and user supplied options.
- Also, as gpgv has no options to enforce a certain reduced style of
+ Also, as gpg has no options to enforce a certain reduced style of
clear-signed files (=the complete content of the file is signed and
the content isn't encoded) we do a divide and conquer approach here
- and split up the clear-signed file in message and signature for gpgv
+ and split up the clear-signed file in message and signature for gpg.
+ And as a cherry on the cake, we use our apt-key wrapper to do part
+ of the lifting in regards to merging keyrings. Fun for the whole family.
*/
void ExecGPGV(std::string const &File, std::string const &FileGPG,
int const &statusfd, int fd[2])
{
#define EINTERNAL 111
- std::string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
- // FIXME: remove support for deprecated APT::GPGV setting
- std::string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted"));
- std::string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts");
+ std::string const aptkey = _config->FindFile("Dir::Bin::apt-key", "/usr/bin/apt-key");
bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
- if (Debug == true)
- {
- std::clog << "gpgv path: " << gpgvpath << std::endl;
- std::clog << "Keyring file: " << trustedFile << std::endl;
- std::clog << "Keyring path: " << trustedPath << std::endl;
- }
-
- std::vector<std::string> keyrings;
- if (DirectoryExists(trustedPath))
- keyrings = GetListOfFilesInDir(trustedPath, "gpg", false, true);
- if (RealFileExists(trustedFile) == true)
- keyrings.push_back(trustedFile);
-
std::vector<const char *> Args;
- Args.reserve(30);
-
- if (keyrings.empty() == true)
- {
- // TRANSLATOR: %s is the trusted keyring parts directory
- ioprintf(std::cerr, _("No keyring installed in %s."),
- _config->FindDir("Dir::Etc::TrustedParts").c_str());
- exit(EINTERNAL);
- }
+ Args.reserve(10);
- Args.push_back(gpgvpath.c_str());
- Args.push_back("--ignore-time-conflict");
+ Args.push_back(aptkey.c_str());
+ Args.push_back("--quiet");
+ Args.push_back("--readonly");
+ Args.push_back("verify");
char statusfdstr[10];
if (statusfd != -1)
@@ -85,13 +65,6 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
Args.push_back(statusfdstr);
}
- for (std::vector<std::string>::const_iterator K = keyrings.begin();
- K != keyrings.end(); ++K)
- {
- Args.push_back("--keyring");
- Args.push_back(K->c_str());
- }
-
Configuration::Item const *Opts;
Opts = _config->Tree("Acquire::gpgv::Options");
if (Opts != 0)
@@ -160,7 +133,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
if (Debug == true)
{
- std::clog << "Preparing to exec: " << gpgvpath;
+ std::clog << "Preparing to exec: ";
for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a)
std::clog << " " << *a;
std::clog << std::endl;
@@ -168,7 +141,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
if (statusfd != -1)
{
- int const nullfd = open("/dev/null", O_RDONLY);
+ int const nullfd = open("/dev/null", O_WRONLY);
close(fd[0]);
// Redirect output to /dev/null; we read from the status fd
if (statusfd != STDOUT_FILENO)
@@ -185,7 +158,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
if (releaseSignature == DETACHED)
{
- execvp(gpgvpath.c_str(), (char **) &Args[0]);
+ execvp(Args[0], (char **) &Args[0]);
ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
exit(EINTERNAL);
}
@@ -205,7 +178,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
{
if (statusfd != -1)
dup2(fd[1], statusfd);
- execvp(gpgvpath.c_str(), (char **) &Args[0]);
+ execvp(Args[0], (char **) &Args[0]);
ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
UNLINK_EXIT(EINTERNAL);
}
@@ -216,7 +189,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
{
if (errno == EINTR)
continue;
- ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "gpgv");
+ ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "apt-key");
UNLINK_EXIT(EINTERNAL);
}
#undef UNLINK_EXIT
@@ -229,14 +202,14 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
// check if it exit'ed normally …
if (WIFEXITED(Status) == false)
{
- ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "gpgv");
+ ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "apt-key");
exit(EINTERNAL);
}
// … and with a good exit code
if (WEXITSTATUS(Status) != 0)
{
- ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "gpgv", WEXITSTATUS(Status));
+ ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "apt-key", WEXITSTATUS(Status));
exit(WEXITSTATUS(Status));
}
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index bb11a3fca..0fa443b4a 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -29,7 +29,7 @@
const char * HashString::_SupportedHashes[] =
{
- "SHA512", "SHA256", "SHA1", "MD5Sum", NULL
+ "SHA512", "SHA256", "SHA1", "MD5Sum", "Checksum-FileSize", NULL
};
HashString::HashString()
@@ -111,6 +111,8 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/
SHA512.AddFD(Fd);
fileHash = (std::string)SHA512.Result();
}
+ else if (strcasecmp(Type.c_str(), "Checksum-FileSize") == 0)
+ strprintf(fileHash, "%llu", Fd.FileSize());
Fd.Close();
return fileHash;
@@ -141,11 +143,27 @@ APT_PURE bool HashString::operator!=(HashString const &other) const
}
/*}}}*/
+bool HashStringList::usable() const /*{{{*/
+{
+ if (empty() == true)
+ return false;
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == true)
+ {
+ // FileSize alone isn't usable
+ for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+ if (hs->HashType() != "Checksum-FileSize")
+ return true;
+ return false;
+ }
+ return find(forcedType) != NULL;
+}
+ /*}}}*/
HashString const * HashStringList::find(char const * const type) const /*{{{*/
{
if (type == NULL || type[0] == '\0')
{
- std::string forcedType = _config->Find("Acquire::ForceHash", "");
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
if (forcedType.empty() == false)
return find(forcedType.c_str());
for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
@@ -186,16 +204,35 @@ bool HashStringList::push_back(const HashString &hashString) /*{{{*/
/*}}}*/
bool HashStringList::VerifyFile(std::string filename) const /*{{{*/
{
- if (list.empty() == true)
- return false;
- HashString const * const hs = find(NULL);
- if (hs == NULL || hs->VerifyFile(filename) == false)
+ if (usable() == false)
return false;
- return true;
+
+ Hashes hashes(*this);
+ FileFd file(filename, FileFd::ReadOnly);
+ HashString const * const hsf = find("Checksum-FileSize");
+ if (hsf != NULL)
+ {
+ std::string fileSize;
+ strprintf(fileSize, "%llu", file.FileSize());
+ if (hsf->HashValue() != fileSize)
+ return false;
+ }
+ hashes.AddFD(file);
+ HashStringList const hsl = hashes.GetHashStringList();
+ return hsl == *this;
}
/*}}}*/
bool HashStringList::operator==(HashStringList const &other) const /*{{{*/
{
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == false)
+ {
+ HashString const * const hs = find(forcedType);
+ HashString const * const ohs = other.find(forcedType);
+ if (hs == NULL || ohs == NULL)
+ return false;
+ return *hs == *ohs;
+ }
short matches = 0;
for (const_iterator hs = begin(); hs != end(); ++hs)
{
@@ -216,11 +253,38 @@ bool HashStringList::operator!=(HashStringList const &other) const
}
/*}}}*/
-// Hashes::AddFD - Add the contents of the FD /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512)
+// PrivateHashes /*{{{*/
+class PrivateHashes {
+public:
+ unsigned long long FileSize;
+ unsigned int CalcHashes;
+
+ PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {}
+};
+ /*}}}*/
+// Hashes::Add* - Add the contents of data or FD /*{{{*/
+bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size)
+{
+ bool Res = true;
+APT_IGNORE_DEPRECATED_PUSH
+ if ((d->CalcHashes & MD5SUM) == MD5SUM)
+ Res &= MD5.Add(Data, Size);
+ if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
+ Res &= SHA1.Add(Data, Size);
+ if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
+ Res &= SHA256.Add(Data, Size);
+ if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
+ Res &= SHA512.Add(Data, Size);
+APT_IGNORE_DEPRECATED_POP
+ d->FileSize += Size;
+ return Res;
+}
+bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes)
+{
+ d->CalcHashes = Hashes;
+ return Add(Data, Size);
+}
+bool Hashes::AddFD(int const Fd,unsigned long long Size)
{
unsigned char Buf[64*64];
bool const ToEOF = (Size == UntilEOF);
@@ -234,19 +298,17 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5,
if (ToEOF && Res == 0) // EOF
break;
Size -= Res;
- if (addMD5 == true)
- MD5.Add(Buf,Res);
- if (addSHA1 == true)
- SHA1.Add(Buf,Res);
- if (addSHA256 == true)
- SHA256.Add(Buf,Res);
- if (addSHA512 == true)
- SHA512.Add(Buf,Res);
+ if (Add(Buf, Res) == false)
+ return false;
}
return true;
}
-bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512)
+bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes)
+{
+ d->CalcHashes = Hashes;
+ return AddFD(Fd, Size);
+}
+bool Hashes::AddFD(FileFd &Fd,unsigned long long Size)
{
unsigned char Buf[64*64];
bool const ToEOF = (Size == 0);
@@ -265,15 +327,49 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5,
else if (a == 0) // EOF
break;
Size -= a;
- if (addMD5 == true)
- MD5.Add(Buf, a);
- if (addSHA1 == true)
- SHA1.Add(Buf, a);
- if (addSHA256 == true)
- SHA256.Add(Buf, a);
- if (addSHA512 == true)
- SHA512.Add(Buf, a);
+ if (Add(Buf, a) == false)
+ return false;
}
return true;
}
+bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes)
+{
+ d->CalcHashes = Hashes;
+ return AddFD(Fd, Size);
+}
/*}}}*/
+HashStringList Hashes::GetHashStringList()
+{
+ HashStringList hashes;
+APT_IGNORE_DEPRECATED_PUSH
+ if ((d->CalcHashes & MD5SUM) == MD5SUM)
+ hashes.push_back(HashString("MD5Sum", MD5.Result().Value()));
+ if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
+ hashes.push_back(HashString("SHA1", SHA1.Result().Value()));
+ if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
+ hashes.push_back(HashString("SHA256", SHA256.Result().Value()));
+ if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
+ hashes.push_back(HashString("SHA512", SHA512.Result().Value()));
+APT_IGNORE_DEPRECATED_POP
+ std::string SizeStr;
+ strprintf(SizeStr, "%llu", d->FileSize);
+ hashes.push_back(HashString("Checksum-FileSize", SizeStr));
+ return hashes;
+}
+APT_IGNORE_DEPRECATED_PUSH
+Hashes::Hashes() { d = new PrivateHashes(~0); }
+Hashes::Hashes(unsigned int const Hashes) { d = new PrivateHashes(Hashes); }
+Hashes::Hashes(HashStringList const &Hashes) {
+ unsigned int calcHashes = Hashes.usable() ? 0 : ~0;
+ if (Hashes.find("MD5Sum") != NULL)
+ calcHashes |= MD5SUM;
+ if (Hashes.find("SHA1") != NULL)
+ calcHashes |= SHA1SUM;
+ if (Hashes.find("SHA256") != NULL)
+ calcHashes |= SHA256SUM;
+ if (Hashes.find("SHA512") != NULL)
+ calcHashes |= SHA512SUM;
+ d = new PrivateHashes(calcHashes);
+}
+Hashes::~Hashes() { delete d; }
+APT_IGNORE_DEPRECATED_POP
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 5a4213868..ac13c8ace 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -53,9 +53,10 @@ class HashString
HashString();
// get hash type used
- std::string HashType() { return Type; };
std::string HashType() const { return Type; };
std::string HashValue() const { return Hash; };
+ APT_DEPRECATED std::string HashType() { return Type; };
+ APT_DEPRECATED std::string HashValue() { return Hash; };
// verify the given filename against the currently loaded hash
bool VerifyFile(std::string filename) const;
@@ -115,6 +116,15 @@ class HashStringList
*/
bool empty() const { return list.empty(); }
+ /** has the list at least one good entry
+ *
+ * similar to #empty, but handles forced hashes.
+ *
+ * @return if no hash is forced, same result as #empty,
+ * if one is forced \b true if this has is available, \b false otherwise
+ */
+ bool usable() const;
+
typedef std::vector<HashString>::const_iterator const_iterator;
/** iterator to the first element */
@@ -129,8 +139,10 @@ class HashStringList
/** compare two HashStringList for similarity.
*
* Two lists are similar if at least one hashtype is in both lists
- * and the hashsum matches. All hashes are checked, if one doesn't
- * match false is returned regardless of how many matched before.
+ * and the hashsum matches. All hashes are checked by default,
+ * if one doesn't match false is returned regardless of how many
+ * matched before. If a hash is forced, only this hash is compared,
+ * all others are ignored.
*/
bool operator==(HashStringList const &other) const;
bool operator!=(HashStringList const &other) const;
@@ -151,32 +163,73 @@ class HashStringList
std::vector<HashString> list;
};
+class PrivateHashes;
class Hashes
{
+ PrivateHashes *d;
+
public:
+ /* those will disappear in the future as it is hard to add new ones this way.
+ * Use Add* to build the results and get them via GetHashStringList() instead */
+ APT_DEPRECATED MD5Summation MD5;
+ APT_DEPRECATED SHA1Summation SHA1;
+ APT_DEPRECATED SHA256Summation SHA256;
+ APT_DEPRECATED SHA512Summation SHA512;
- MD5Summation MD5;
- SHA1Summation SHA1;
- SHA256Summation SHA256;
- SHA512Summation SHA512;
-
static const int UntilEOF = 0;
- inline bool Add(const unsigned char *Data,unsigned long long Size)
+ bool Add(const unsigned char * const Data, unsigned long long const Size);
+ APT_DEPRECATED bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes);
+ inline bool Add(const char * const Data)
+ {return Add((unsigned char const * const)Data,strlen(Data));};
+ inline bool Add(const unsigned char * const Beg,const unsigned char * const End)
+ {return Add(Beg,End-Beg);};
+
+ enum SupportedHashes { MD5SUM = (1 << 0), SHA1SUM = (1 << 1), SHA256SUM = (1 << 2),
+ SHA512SUM = (1 << 3) };
+ bool AddFD(int const Fd,unsigned long long Size = 0);
+ APT_DEPRECATED bool AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes);
+ bool AddFD(FileFd &Fd,unsigned long long Size = 0);
+ APT_DEPRECATED bool AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes);
+
+ HashStringList GetHashStringList();
+
+APT_IGNORE_DEPRECATED_PUSH
+ /** create a Hashes object to calculate all supported hashes
+ *
+ * If ALL is too much, you can limit which Hashes are calculated
+ * with the following other constructors which mention explicitly
+ * which hashes to generate. */
+ Hashes();
+ /** @param Hashes bitflag composed of #SupportedHashes */
+ Hashes(unsigned int const Hashes);
+ /** @param Hashes is a list of hashes */
+ Hashes(HashStringList const &Hashes);
+ virtual ~Hashes();
+APT_IGNORE_DEPRECATED_POP
+
+ private:
+ APT_HIDDEN APT_CONST inline unsigned int boolsToFlag(bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512)
{
- return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size) && SHA512.Add(Data,Size);
+ unsigned int Hashes = ~0;
+ if (addMD5 == false) Hashes &= ~MD5SUM;
+ if (addSHA1 == false) Hashes &= ~SHA1SUM;
+ if (addSHA256 == false) Hashes &= ~SHA256SUM;
+ if (addSHA512 == false) Hashes &= ~SHA512SUM;
+ return Hashes;
+ }
+
+ public:
+APT_IGNORE_DEPRECATED_PUSH
+ APT_DEPRECATED bool AddFD(int const Fd, unsigned long long Size, bool const addMD5,
+ bool const addSHA1, bool const addSHA256, bool const addSHA512) {
+ return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
+ };
+ APT_DEPRECATED bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5,
+ bool const addSHA1, bool const addSHA256, bool const addSHA512) {
+ return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
};
- inline bool Add(const char *Data) {return Add((unsigned char const *)Data,strlen(Data));};
- inline bool AddFD(int const Fd,unsigned long long Size = 0)
- { return AddFD(Fd, Size, true, true, true, true); };
- bool AddFD(int const Fd, unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512);
- inline bool AddFD(FileFd &Fd,unsigned long long Size = 0)
- { return AddFD(Fd, Size, true, true, true, true); };
- bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512);
- inline bool Add(const unsigned char *Beg,const unsigned char *End)
- {return Add(Beg,End-Beg);};
+APT_IGNORE_DEPRECATED_POP
};
#endif
diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h
index 2d6448e5e..2f9c6c269 100644
--- a/apt-pkg/contrib/macros.h
+++ b/apt-pkg/contrib/macros.h
@@ -89,7 +89,7 @@
#define APT_MUSTCHECK __attribute__((warn_unused_result))
#else
#define APT_NONNULL(...)
- #define APT_REQRET
+ #define APT_MUSTCHECK
#endif
#if APT_GCC_VERSION >= 0x0400
@@ -132,13 +132,30 @@
#endif
#endif
+#if __GNUC__ >= 4
+ #define APT_IGNORE_DEPRECATED_PUSH \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+ #define APT_IGNORE_DEPRECATED_POP \
+ _Pragma("GCC diagnostic pop")
+ #define APT_IGNORE_DEPRECATED(XXX) \
+ APT_IGNORE_DEPRECATED_PUSH \
+ XXX \
+ APT_IGNORE_DEPRECATED_POP
+#else
+ #define APT_IGNORE_DEPRECATED_PUSH
+ #define APT_IGNORE_DEPRECATED_POP
+ #define APT_IGNORE_DEPRECATED(XXX) XXX
+#endif
+
// These lines are extracted by the makefiles and the buildsystem
// Increasing MAJOR or MINOR results in the need of recompiling all
// reverse-dependencies of libapt-pkg against the new SONAME.
// Non-ABI-Breaks should only increase RELEASE number.
// See also buildlib/libversion.mak
#define APT_PKG_MAJOR 4
-#define APT_PKG_MINOR 12
+#define APT_PKG_MINOR 15
#define APT_PKG_RELEASE 0
+#define APT_PKG_ABI ((APT_PKG_MAJOR * 100) + APT_PKG_MINOR)
#endif
diff --git a/apt-pkg/contrib/netrc.cc b/apt-pkg/contrib/netrc.cc
index feaed67c8..1e3778f45 100644
--- a/apt-pkg/contrib/netrc.cc
+++ b/apt-pkg/contrib/netrc.cc
@@ -152,18 +152,6 @@ static int parsenetrc_string (char *host, std::string &login, std::string &passw
return retcode;
}
-// for some unknown reason this method is exported so keep a compatible interface for now …
-int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
-{
- std::string login_string, password_string;
- int const ret = parsenetrc_string(host, login_string, password_string, netrcfile);
- if (ret < 0)
- return ret;
- strncpy(login, login_string.c_str(), LOGINSIZE - 1);
- strncpy(password, password_string.c_str(), PASSWORDSIZE - 1);
- return ret;
-}
-
void maybe_add_auth (URI &Uri, string NetRCFile)
{
diff --git a/apt-pkg/contrib/netrc.h b/apt-pkg/contrib/netrc.h
index dbeb45386..b5b56f5d4 100644
--- a/apt-pkg/contrib/netrc.h
+++ b/apt-pkg/contrib/netrc.h
@@ -27,9 +27,5 @@
class URI;
-// FIXME: kill this export on the next ABI break - strongly doubt its in use anyway
-// outside of the apt itself, its really a internal interface
-APT_DEPRECATED int parsenetrc (char *host, char *login, char *password, char *filename);
-
void maybe_add_auth (URI &Uri, std::string NetRCFile);
#endif
diff --git a/apt-pkg/contrib/sha2_internal.cc b/apt-pkg/contrib/sha2_internal.cc
index 131ff5beb..f70b7b17d 100644
--- a/apt-pkg/contrib/sha2_internal.cc
+++ b/apt-pkg/contrib/sha2_internal.cc
@@ -129,6 +129,14 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
/*** ENDIAN REVERSAL MACROS *******************************************/
#if BYTE_ORDER == LITTLE_ENDIAN
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+#define REVERSE32(w,x) { \
+ (x) = __builtin_bswap32(w); \
+}
+#define REVERSE64(w,x) { \
+ (x) = __builtin_bswap64(w); \
+}
+#else
#define REVERSE32(w,x) { \
sha2_word32 tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
@@ -142,6 +150,7 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
((tmp & 0x0000ffff0000ffffULL) << 16); \
}
+#endif
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/*
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 87f57a30e..0db4c57b2 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -74,6 +74,13 @@ bool Endswith(const std::string &s, const std::string &end)
return (s.substr(s.size() - end.size(), s.size()) == end);
}
+bool Startswith(const std::string &s, const std::string &start)
+{
+ if (start.size() > s.size())
+ return false;
+ return (s.substr(0, start.size()) == start);
+}
+
}
}
/*}}}*/
@@ -317,21 +324,19 @@ bool ParseCWord(const char *&String,string &Res)
/* */
string QuoteString(const string &Str, const char *Bad)
{
- string Res;
+ std::stringstream Res;
for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
{
- if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
+ if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
*I == 0x25 || // percent '%' char
*I <= 0x20 || *I >= 0x7F) // control chars
{
- char Buf[10];
- sprintf(Buf,"%%%02x",(int)*I);
- Res += Buf;
+ ioprintf(Res,"%%%02x",(int)*I);
}
else
- Res += *I;
+ Res << *I;
}
- return Res;
+ return Res.str();
}
/*}}}*/
// DeQuoteString - Convert a string from quoted from /*{{{*/
@@ -372,13 +377,12 @@ string DeQuoteString(string::const_iterator const &begin,
YottaBytes (E24) */
string SizeToStr(double Size)
{
- char S[300];
double ASize;
if (Size >= 0)
ASize = Size;
else
ASize = -1*Size;
-
+
/* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes,
ExaBytes, ZettaBytes, YottaBytes */
char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'};
@@ -387,20 +391,21 @@ string SizeToStr(double Size)
{
if (ASize < 100 && I != 0)
{
- sprintf(S,"%'.1f %c",ASize,Ext[I]);
- break;
+ std::string S;
+ strprintf(S, "%'.1f %c", ASize, Ext[I]);
+ return S;
}
-
+
if (ASize < 10000)
{
- sprintf(S,"%'.0f %c",ASize,Ext[I]);
- break;
+ std::string S;
+ strprintf(S, "%'.0f %c", ASize, Ext[I]);
+ return S;
}
ASize /= 1000.0;
I++;
}
-
- return S;
+ return "";
}
/*}}}*/
// TimeToStr - Convert the time into a string /*{{{*/
@@ -408,36 +413,27 @@ string SizeToStr(double Size)
/* Converts a number of seconds to a hms format */
string TimeToStr(unsigned long Sec)
{
- char S[300];
-
- while (1)
+ std::string S;
+ if (Sec > 60*60*24)
{
- if (Sec > 60*60*24)
- {
- //d means days, h means hours, min means minutes, s means seconds
- sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
- break;
- }
-
- if (Sec > 60*60)
- {
- //h means hours, min means minutes, s means seconds
- sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
- break;
- }
-
- if (Sec > 60)
- {
- //min means minutes, s means seconds
- sprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
- break;
- }
-
- //s means seconds
- sprintf(S,_("%lis"),Sec);
- break;
+ //TRANSLATOR: d means days, h means hours, min means minutes, s means seconds
+ strprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+ }
+ else if (Sec > 60*60)
+ {
+ //TRANSLATOR: h means hours, min means minutes, s means seconds
+ strprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
+ }
+ else if (Sec > 60)
+ {
+ //TRANSLATOR: min means minutes, s means seconds
+ strprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
+ }
+ else
+ {
+ //TRANSLATOR: s means seconds
+ strprintf(S,_("%lis"),Sec);
}
-
return S;
}
/*}}}*/
@@ -772,86 +768,94 @@ string TimeRFC1123(time_t Date)
In particular: this reads blocks from the input until it believes
that it's run out of input text. Each block is terminated by a
- double newline ('\n' followed by '\n'). As noted below, there is a
- bug in this code: it assumes that all the blocks have been read if
- it doesn't see additional text in the buffer after the last one is
- parsed, which will cause it to lose blocks if the last block
- coincides with the end of the buffer.
+ double newline ('\n' followed by '\n').
*/
bool ReadMessages(int Fd, vector<string> &List)
{
char Buffer[64000];
- char *End = Buffer;
// Represents any left-over from the previous iteration of the
// parse loop. (i.e., if a message is split across the end
// of the buffer, it goes here)
string PartialMessage;
-
- while (1)
- {
- int Res = read(Fd,End,sizeof(Buffer) - (End-Buffer));
+
+ do {
+ int const Res = read(Fd, Buffer, sizeof(Buffer));
if (Res < 0 && errno == EINTR)
continue;
-
- // Process is dead, this is kind of bad..
+
+ // process we read from has died
if (Res == 0)
return false;
-
+
// No data
- if (Res < 0 && errno == EAGAIN)
+ if (Res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
return true;
if (Res < 0)
return false;
-
- End += Res;
-
- // Look for the end of the message
- for (char *I = Buffer; I + 1 < End; I++)
+
+ // extract the message(s) from the buffer
+ char const *Start = Buffer;
+ char const * const End = Buffer + Res;
+
+ char const * NL = (char const *) memchr(Start, '\n', End - Start);
+ if (NL == NULL)
{
- if (I[1] != '\n' ||
- (I[0] != '\n' && strncmp(I, "\r\n\r\n", 4) != 0))
- continue;
-
- // Pull the message out
- string Message(Buffer,I-Buffer);
- PartialMessage += Message;
-
- // Fix up the buffer
- for (; I < End && (*I == '\n' || *I == '\r'); ++I);
- End -= I-Buffer;
- memmove(Buffer,I,End-Buffer);
- I = Buffer;
-
- List.push_back(PartialMessage);
- PartialMessage.clear();
+ // end of buffer: store what we have so far and read new data in
+ PartialMessage.append(Start, End - Start);
+ Start = End;
}
- if (End != Buffer)
- {
- // If there's text left in the buffer, store it
- // in PartialMessage and throw the rest of the buffer
- // away. This allows us to handle messages that
- // are longer than the static buffer size.
- PartialMessage += string(Buffer, End);
- End = Buffer;
- }
else
- {
- // BUG ALERT: if a message block happens to end at a
- // multiple of 64000 characters, this will cause it to
- // terminate early, leading to a badly formed block and
- // probably crashing the method. However, this is the only
- // way we have to find the end of the message block. I have
- // an idea of how to fix this, but it will require changes
- // to the protocol (essentially to mark the beginning and
- // end of the block).
- //
- // -- dburrows 2008-04-02
- return true;
- }
+ ++NL;
+
+ if (PartialMessage.empty() == false && Start < End)
+ {
+ // if we start with a new line, see if the partial message we have ended with one
+ // so that we properly detect records ending between two read() runs
+ // cases are: \n|\n , \r\n|\r\n and \r\n\r|\n
+ // the case \r|\n\r\n is handled by the usual double-newline handling
+ if ((NL - Start) == 1 || ((NL - Start) == 2 && *Start == '\r'))
+ {
+ if (APT::String::Endswith(PartialMessage, "\n") || APT::String::Endswith(PartialMessage, "\r\n\r"))
+ {
+ PartialMessage.erase(PartialMessage.find_last_not_of("\r\n") + 1);
+ List.push_back(PartialMessage);
+ PartialMessage.clear();
+ while (NL < End && (*NL == '\n' || *NL == '\r')) ++NL;
+ Start = NL;
+ }
+ }
+ }
+
+ while (Start < End) {
+ char const * NL2 = (char const *) memchr(NL, '\n', End - NL);
+ if (NL2 == NULL)
+ {
+ // end of buffer: store what we have so far and read new data in
+ PartialMessage.append(Start, End - Start);
+ break;
+ }
+ ++NL2;
+
+ // did we find a double newline?
+ if ((NL2 - NL) == 1 || ((NL2 - NL) == 2 && *NL == '\r'))
+ {
+ PartialMessage.append(Start, NL2 - Start);
+ PartialMessage.erase(PartialMessage.find_last_not_of("\r\n") + 1);
+ List.push_back(PartialMessage);
+ PartialMessage.clear();
+ while (NL2 < End && (*NL2 == '\n' || *NL2 == '\r')) ++NL2;
+ Start = NL2;
+ }
+ NL = NL2;
+ }
+
+ // we have read at least one complete message and nothing left
+ if (PartialMessage.empty() == true)
+ return true;
if (WaitFd(Fd) == false)
return false;
- }
+ } while (true);
}
/*}}}*/
// MonthConv - Converts a month string into a number /*{{{*/
@@ -1061,7 +1065,7 @@ bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base
// ---------------------------------------------------------------------
/* This is used in decoding the 256bit encoded fixed length fields in
tar files */
-bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+bool Base256ToNum(const char *Str,unsigned long long &Res,unsigned int Len)
{
if ((Str[0] & 0x80) == 0)
return false;
@@ -1074,6 +1078,23 @@ bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
}
}
/*}}}*/
+// Base256ToNum - Convert a fixed length binary to a number /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used in decoding the 256bit encoded fixed length fields in
+ tar files */
+bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+{
+ unsigned long long Num;
+ bool rc;
+
+ rc = Base256ToNum(Str, Num, Len);
+ Res = Num;
+ if (Res != Num)
+ return false;
+
+ return rc;
+}
+ /*}}}*/
// HexDigit - Convert a hex character into an integer /*{{{*/
// ---------------------------------------------------------------------
/* Helper for Hex2Num */
@@ -1287,10 +1308,12 @@ void ioprintf(ostream &out,const char *format,...)
va_list args;
ssize_t size = 400;
while (true) {
+ bool ret = false;
va_start(args,format);
- if (iovprintf(out, format, args, size) == true)
- return;
+ ret = iovprintf(out, format, args, size);
va_end(args);
+ if (ret == true)
+ return;
}
}
void strprintf(string &out,const char *format,...)
@@ -1299,10 +1322,12 @@ void strprintf(string &out,const char *format,...)
ssize_t size = 400;
std::ostringstream outstr;
while (true) {
+ bool ret = false;
va_start(args,format);
- if (iovprintf(outstr, format, args, size) == true)
- break;
+ ret = iovprintf(outstr, format, args, size);
va_end(args);
+ if (ret == true)
+ break;
}
out = outstr.str();
}
@@ -1387,7 +1412,7 @@ size_t strv_length(const char **str_array)
;
return i;
}
-
+ /*}}}*/
// DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -1569,51 +1594,46 @@ void URI::CopyFrom(const string &U)
/* */
URI::operator string()
{
- string Res;
-
+ std::stringstream Res;
+
if (Access.empty() == false)
- Res = Access + ':';
-
+ Res << Access << ':';
+
if (Host.empty() == false)
- {
+ {
if (Access.empty() == false)
- Res += "//";
-
+ Res << "//";
+
if (User.empty() == false)
{
// FIXME: Technically userinfo is permitted even less
// characters than these, but this is not conveniently
// expressed with a blacklist.
- Res += QuoteString(User, ":/?#[]@");
+ Res << QuoteString(User, ":/?#[]@");
if (Password.empty() == false)
- Res += ":" + QuoteString(Password, ":/?#[]@");
- Res += "@";
+ Res << ":" << QuoteString(Password, ":/?#[]@");
+ Res << "@";
}
-
+
// Add RFC 2732 escaping characters
- if (Access.empty() == false &&
- (Host.find('/') != string::npos || Host.find(':') != string::npos))
- Res += '[' + Host + ']';
+ if (Access.empty() == false && Host.find_first_of("/:") != string::npos)
+ Res << '[' << Host << ']';
else
- Res += Host;
-
+ Res << Host;
+
if (Port != 0)
- {
- char S[30];
- sprintf(S,":%u",Port);
- Res += S;
- }
+ Res << ':' << Port;
}
-
+
if (Path.empty() == false)
{
if (Path[0] != '/')
- Res += "/" + Path;
+ Res << "/" << Path;
else
- Res += Path;
+ Res << Path;
}
-
- return Res;
+
+ return Res.str();
}
/*}}}*/
// URI::SiteOnly - Return the schema and site for the URI /*{{{*/
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index f4f80834b..d64270aaf 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -40,6 +40,7 @@ namespace APT {
namespace String {
std::string Strip(const std::string &s);
bool Endswith(const std::string &s, const std::string &ending);
+ bool Startswith(const std::string &s, const std::string &starting);
}
}
@@ -72,6 +73,7 @@ bool ReadMessages(int Fd, std::vector<std::string> &List);
bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0);
bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base = 0);
bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
+bool Base256ToNum(const char *Str,unsigned long long &Res,unsigned int Len);
bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length);
// input changing string split
@@ -151,9 +153,9 @@ inline const char *DeNull(const char *s) {return (s == 0?"(null)":s);}
class URI
{
void CopyFrom(const std::string &From);
-
+
public:
-
+
std::string Access;
std::string User;
std::string Password;