|
|
@@ -887,6 +887,28 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
// create log
|
|
|
OpenLog();
|
|
|
|
|
|
+ // Generate the base argument list for dpkg
|
|
|
+ std::vector<const char *> Args;
|
|
|
+ unsigned long StartSize = 0;
|
|
|
+ string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
|
|
|
+ Args.push_back(Tmp.c_str());
|
|
|
+ StartSize += Tmp.length();
|
|
|
+
|
|
|
+ // Stick in any custom dpkg options
|
|
|
+ Configuration::Item const *Opts = _config->Tree("DPkg::Options");
|
|
|
+ if (Opts != 0)
|
|
|
+ {
|
|
|
+ Opts = Opts->Child;
|
|
|
+ for (; Opts != 0; Opts = Opts->Next)
|
|
|
+ {
|
|
|
+ if (Opts->Value.empty() == true)
|
|
|
+ continue;
|
|
|
+ Args.push_back(Opts->Value.c_str());
|
|
|
+ StartSize += Opts->Value.length();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ size_t const BaseArgs = Args.size();
|
|
|
+
|
|
|
// this loop is runs once per operation
|
|
|
for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
|
|
|
{
|
|
|
@@ -908,11 +930,12 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
for (; J != List.end() && J->Op == I->Op; ++J)
|
|
|
/* nothing */;
|
|
|
|
|
|
- // Generate the argument list
|
|
|
- const char *Args[MaxArgs + 50];
|
|
|
// keep track of allocated strings for multiarch package names
|
|
|
- char *Packages[MaxArgs + 50];
|
|
|
- unsigned int pkgcount = 0;
|
|
|
+ std::vector<char *> Packages;
|
|
|
+
|
|
|
+ // start with the baseset of arguments
|
|
|
+ unsigned long Size = StartSize;
|
|
|
+ Args.erase(Args.begin() + BaseArgs, Args.end());
|
|
|
|
|
|
// Now check if we are within the MaxArgs limit
|
|
|
//
|
|
|
@@ -922,91 +945,67 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
// - with the split they may now be configured in different
|
|
|
// runs
|
|
|
if (J - I > (signed)MaxArgs)
|
|
|
+ {
|
|
|
J = I + MaxArgs;
|
|
|
-
|
|
|
- unsigned int n = 0;
|
|
|
- unsigned long Size = 0;
|
|
|
- string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
|
|
|
- Args[n++] = Tmp.c_str();
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
-
|
|
|
- // Stick in any custom dpkg options
|
|
|
- Configuration::Item const *Opts = _config->Tree("DPkg::Options");
|
|
|
- if (Opts != 0)
|
|
|
+ Args.reserve(MaxArgs + 10);
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- Opts = Opts->Child;
|
|
|
- for (; Opts != 0; Opts = Opts->Next)
|
|
|
- {
|
|
|
- if (Opts->Value.empty() == true)
|
|
|
- continue;
|
|
|
- Args[n++] = Opts->Value.c_str();
|
|
|
- Size += Opts->Value.length();
|
|
|
- }
|
|
|
+ Args.reserve((J - I) + 10);
|
|
|
}
|
|
|
+
|
|
|
|
|
|
- char status_fd_buf[20];
|
|
|
int fd[2];
|
|
|
pipe(fd);
|
|
|
-
|
|
|
- Args[n++] = "--status-fd";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+
|
|
|
+#define ADDARG(X) Args.push_back(X); Size += strlen(X)
|
|
|
+#define ADDARGC(X) Args.push_back(X); Size += sizeof(X) - 1
|
|
|
+
|
|
|
+ ADDARGC("--status-fd");
|
|
|
+ char status_fd_buf[20];
|
|
|
snprintf(status_fd_buf,sizeof(status_fd_buf),"%i", fd[1]);
|
|
|
- Args[n++] = status_fd_buf;
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARG(status_fd_buf);
|
|
|
|
|
|
switch (I->Op)
|
|
|
{
|
|
|
case Item::Remove:
|
|
|
- Args[n++] = "--force-depends";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--force-remove-essential";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--remove";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--force-depends");
|
|
|
+ ADDARGC("--force-remove-essential");
|
|
|
+ ADDARGC("--remove");
|
|
|
break;
|
|
|
|
|
|
case Item::Purge:
|
|
|
- Args[n++] = "--force-depends";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--force-remove-essential";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--purge";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--force-depends");
|
|
|
+ ADDARGC("--force-remove-essential");
|
|
|
+ ADDARGC("--purge");
|
|
|
break;
|
|
|
|
|
|
case Item::Configure:
|
|
|
- Args[n++] = "--configure";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--configure");
|
|
|
break;
|
|
|
|
|
|
case Item::ConfigurePending:
|
|
|
- Args[n++] = "--configure";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--pending";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--configure");
|
|
|
+ ADDARGC("--pending");
|
|
|
break;
|
|
|
|
|
|
case Item::TriggersPending:
|
|
|
- Args[n++] = "--triggers-only";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--pending";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--triggers-only");
|
|
|
+ ADDARGC("--pending");
|
|
|
break;
|
|
|
|
|
|
case Item::Install:
|
|
|
- Args[n++] = "--unpack";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
- Args[n++] = "--auto-deconfigure";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--unpack");
|
|
|
+ ADDARGC("--auto-deconfigure");
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (NoTriggers == true && I->Op != Item::TriggersPending &&
|
|
|
I->Op != Item::ConfigurePending)
|
|
|
{
|
|
|
- Args[n++] = "--no-triggers";
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ ADDARGC("--no-triggers");
|
|
|
}
|
|
|
+#undef ADDARGC
|
|
|
|
|
|
// Write in the file or package names
|
|
|
if (I->Op == Item::Install)
|
|
|
@@ -1015,10 +1014,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
{
|
|
|
if (I->File[0] != '/')
|
|
|
return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
|
|
|
- Args[n++] = I->File.c_str();
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
+ Args.push_back(I->File.c_str());
|
|
|
+ Size += I->File.length();
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
string const nativeArch = _config->Find("APT::Architecture");
|
|
|
@@ -1030,29 +1029,35 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end())
|
|
|
continue;
|
|
|
if (I->Pkg.Arch() == nativeArch || !strcmp(I->Pkg.Arch(), "all"))
|
|
|
- Args[n++] = I->Pkg.Name();
|
|
|
+ {
|
|
|
+ char const * const name = I->Pkg.Name();
|
|
|
+ ADDARG(name);
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
- Packages[pkgcount] = strdup(I->Pkg.FullName(false).c_str());
|
|
|
- Args[n++] = Packages[pkgcount++];
|
|
|
+ char * const fullname = strdup(I->Pkg.FullName(false).c_str());
|
|
|
+ Packages.push_back(fullname);
|
|
|
+ ADDARG(fullname);
|
|
|
}
|
|
|
- Size += strlen(Args[n-1]);
|
|
|
}
|
|
|
// skip configure action if all sheduled packages disappeared
|
|
|
if (oldSize == Size)
|
|
|
continue;
|
|
|
}
|
|
|
- Args[n] = 0;
|
|
|
+#undef ADDARG
|
|
|
+
|
|
|
J = I;
|
|
|
|
|
|
if (_config->FindB("Debug::pkgDPkgPM",false) == true)
|
|
|
{
|
|
|
- for (unsigned int k = 0; k != n; k++)
|
|
|
- clog << Args[k] << ' ';
|
|
|
+ for (std::vector<const char *>::const_iterator a = Args.begin();
|
|
|
+ a != Args.end(); ++a)
|
|
|
+ clog << *a << ' ';
|
|
|
clog << endl;
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
+ Args.push_back(NULL);
|
|
|
+
|
|
|
cout << flush;
|
|
|
clog << flush;
|
|
|
cerr << flush;
|
|
|
@@ -1162,7 +1167,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
/* No Job Control Stop Env is a magic dpkg var that prevents it
|
|
|
from using sigstop */
|
|
|
putenv((char *)"DPKG_NO_TSTP=yes");
|
|
|
- execvp(Args[0],(char **)Args);
|
|
|
+ execvp(Args[0], (char**) &Args[0]);
|
|
|
cerr << "Could not exec dpkg!" << endl;
|
|
|
_exit(100);
|
|
|
}
|
|
|
@@ -1188,10 +1193,11 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
sigemptyset(&sigmask);
|
|
|
sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
|
|
|
|
|
|
- /* clean up the temporary allocation for multiarch package names in
|
|
|
- the parent, so we don't leak memory when we return. */
|
|
|
- for (unsigned int i = 0; i < pkgcount; i++)
|
|
|
- free(Packages[i]);
|
|
|
+ /* free vectors (and therefore memory) as we don't need the included data anymore */
|
|
|
+ for (std::vector<char *>::const_iterator p = Packages.begin();
|
|
|
+ p != Packages.end(); ++p)
|
|
|
+ free(*p);
|
|
|
+ Packages.clear();
|
|
|
|
|
|
// the result of the waitpid call
|
|
|
int res;
|