]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire.cc
prevent C++ locale number formatting in text APIs
[apt.git] / apt-pkg / acquire.cc
index fb1210750f41b3b2699be4e9c9e5d50ccc64662e..29362fb407c96ba21d5bce7e1791d4a624ec5191 100644 (file)
@@ -351,8 +351,42 @@ string pkgAcquire::QueueName(string Uri,MethodConfig const *&Config)
    if (Config->SingleInstance == true || QueueMode == QueueAccess)
       return U.Access;
 
-   string AccessSchema = U.Access + ':',
-       FullQueueName = AccessSchema + U.Host;
+   string AccessSchema = U.Access + ':';
+   string FullQueueName;
+
+   if (U.Host.empty())
+   {
+      long existing = 0;
+      // check how many queues exist already and reuse empty ones
+      for (Queue const *I = Queues; I != 0; I = I->Next)
+        if (I->Name.compare(0, AccessSchema.length(), AccessSchema) == 0)
+        {
+           if (I->Items == nullptr)
+              return I->Name;
+           ++existing;
+        }
+
+#ifdef _SC_NPROCESSORS_ONLN
+      long cpuCount = sysconf(_SC_NPROCESSORS_ONLN) * 2;
+#else
+      long cpuCount = 10;
+#endif
+      cpuCount = _config->FindI("Acquire::QueueHost::Limit", cpuCount);
+
+      if (cpuCount <= 0 || existing < cpuCount)
+        strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), existing);
+      else
+      {
+        long const randomQueue = random() % cpuCount;
+        strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), randomQueue);
+      }
+
+      if (Debug)
+         clog << "Chose random queue " << FullQueueName << " for " << Uri << endl;
+   } else
+   {
+      FullQueueName = AccessSchema + U.Host;
+   }
    unsigned int Instances = 0, SchemaLength = AccessSchema.length();
 
    Queue *I = Queues;
@@ -428,20 +462,30 @@ void pkgAcquire::SetFds(int &Fd,fd_set *RSet,fd_set *WSet)
    }
 }
                                                                        /*}}}*/
-// Acquire::RunFds - Deal with active FDs                              /*{{{*/
+// Acquire::RunFds - compatibility remove on next abi/api break                /*{{{*/
+void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
+{
+   RunFdsSane(RSet, WSet);
+}
+                                                                       /*}}}*/
+// Acquire::RunFdsSane - Deal with active FDs                          /*{{{*/
 // ---------------------------------------------------------------------
 /* Dispatch active FDs over to the proper workers. It is very important
    that a worker never be erased while this is running! The queue class
    should never erase a worker except during shutdown processing. */
-void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
+bool pkgAcquire::RunFdsSane(fd_set *RSet,fd_set *WSet)
 {
+   bool Res = true;
+
    for (Worker *I = Workers; I != 0; I = I->NextAcquire)
    {
       if (I->InFd >= 0 && FD_ISSET(I->InFd,RSet) != 0)
-        I->InFdReady();
+        Res &= I->InFdReady();
       if (I->OutFd >= 0 && FD_ISSET(I->OutFd,WSet) != 0)
-        I->OutFdReady();
+        Res &= I->OutFdReady();
    }
+
+   return Res;
 }
                                                                        /*}}}*/
 // Acquire::Run - Run the fetch sequence                               /*{{{*/
@@ -497,7 +541,11 @@ static void CheckDropPrivsMustBeDisabled(pkgAcquire const &Fetcher)
 
    struct passwd const * const pw = getpwnam(SandboxUser.c_str());
    if (pw == NULL)
+   {
+      _error->Warning(_("No sandbox user '%s' on the system, can not drop privileges"), SandboxUser.c_str());
+      _config->Set("APT::Sandbox::User", "");
       return;
+   }
 
    gid_t const old_euid = geteuid();
    gid_t const old_egid = getegid();
@@ -525,7 +573,7 @@ static void CheckDropPrivsMustBeDisabled(pkgAcquire const &Fetcher)
        I != Fetcher.ItemsEnd(); ++I)
    {
       // no need to drop privileges for a complete file
-      if ((*I)->Complete == true)
+      if ((*I)->Complete == true || (*I)->Status != pkgAcquire::Item::StatIdle)
         continue;
 
       // if destination file is inaccessible all hope is lost for privilege dropping
@@ -604,7 +652,8 @@ pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall)
         break;
       }
 
-      RunFds(&RFds,&WFds);
+      if(RunFdsSane(&RFds,&WFds) == false)
+         break;
 
       // Timeout, notify the log class
       if (Res == 0 || (Log != 0 && Log->Update == true))
@@ -688,6 +737,7 @@ bool pkgAcquire::Clean(string Dir)
       // Skip some files..
       if (strcmp(Dir->d_name,"lock") == 0 ||
          strcmp(Dir->d_name,"partial") == 0 ||
+         strcmp(Dir->d_name,"lost+found") == 0 ||
          strcmp(Dir->d_name,".") == 0 ||
          strcmp(Dir->d_name,"..") == 0)
         continue;
@@ -714,7 +764,7 @@ bool pkgAcquire::Clean(string Dir)
 /* This is the total number of bytes needed */
 APT_PURE unsigned long long pkgAcquire::TotalNeeded()
 {
-   return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+   return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
       [](unsigned long long const T, Item const * const I) {
         return T + I->FileSize;
    });
@@ -725,7 +775,7 @@ APT_PURE unsigned long long pkgAcquire::TotalNeeded()
 /* This is the number of bytes that is not local */
 APT_PURE unsigned long long pkgAcquire::FetchNeeded()
 {
-   return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+   return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
       [](unsigned long long const T, Item const * const I) {
         if (I->Local == false)
            return T + I->FileSize;
@@ -739,7 +789,7 @@ APT_PURE unsigned long long pkgAcquire::FetchNeeded()
 /* This is the number of bytes that is not local */
 APT_PURE unsigned long long pkgAcquire::PartialPresent()
 {
-   return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+   return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
       [](unsigned long long const T, Item const * const I) {
         if (I->Local == false)
            return T + I->PartialSize;
@@ -803,9 +853,8 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item)
 {
    QItem **I = &Items;
    // move to the end of the queue and check for duplicates here
-   HashStringList const hsl = Item.Owner->GetExpectedHashes();
    for (; *I != 0; I = &(*I)->Next)
-      if (Item.URI == (*I)->URI || hsl == (*I)->Owner->GetExpectedHashes())
+      if (Item.URI == (*I)->URI)
       {
         if (_config->FindB("Debug::pkgAcquire::Worker",false) == true)
            std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl;
@@ -1094,11 +1143,11 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
    CurrentBytes = 0;
    TotalItems = 0;
    CurrentItems = 0;
-   
+
    // Compute the total number of bytes to fetch
    unsigned int Unknown = 0;
    unsigned int Count = 0;
-   bool UnfetchedReleaseFiles = false;
+   bool ExpectAdditionalItems = false;
    for (pkgAcquire::ItemCIterator I = Owner->ItemsBegin(); 
         I != Owner->ItemsEnd();
        ++I, ++Count)
@@ -1106,17 +1155,10 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
       TotalItems++;
       if ((*I)->Status == pkgAcquire::Item::StatDone)
         ++CurrentItems;
-      
-      // Totally ignore local items
-      if ((*I)->Local == true)
-        continue;
-
-      // see if the method tells us to expect more
-      TotalItems += (*I)->ExpectedAdditionalItems;
 
-      // check if there are unfetched Release files
-      if ((*I)->Complete == false && (*I)->ExpectedAdditionalItems > 0)
-         UnfetchedReleaseFiles = true;
+      // do we expect to acquire more files than we know of yet?
+      if ((*I)->ExpectedAdditionalItems > 0)
+         ExpectAdditionalItems = true;
 
       TotalBytes += (*I)->FileSize;
       if ((*I)->Complete == true)
@@ -1124,7 +1166,7 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
       if ((*I)->FileSize == 0 && (*I)->Complete == false)
         ++Unknown;
    }
-   
+
    // Compute the current completion
    unsigned long long ResumeSize = 0;
    for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
@@ -1152,12 +1194,6 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
    if (CurrentBytes > TotalBytes)
       CurrentBytes = TotalBytes;
 
-   // debug
-   if (_config->FindB("Debug::acquire::progress", false) == true)
-      std::clog << " Bytes: " 
-                << SizeToStr(CurrentBytes) << " / " << SizeToStr(TotalBytes) 
-                << std::endl;
-   
    // Compute the CPS
    struct timeval NewTime;
    gettimeofday(&NewTime,0);
@@ -1179,12 +1215,27 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
 
    double const OldPercent = Percent;
    // calculate the percentage, if we have too little data assume 1%
-   if (TotalBytes > 0 && UnfetchedReleaseFiles)
+   if (ExpectAdditionalItems)
       Percent = 0;
    else
       // use both files and bytes because bytes can be unreliable
       Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) +
                  0.2 * (CurrentItems/float(TotalItems)*100.0));
+
+   // debug
+   if (_config->FindB("Debug::acquire::progress", false) == true)
+   {
+      std::clog
+         << "["
+         << std::setw(5) << std::setprecision(4) << std::showpoint << Percent 
+         << "]"
+         << " Bytes: "
+         << SizeToStr(CurrentBytes) << " / " << SizeToStr(TotalBytes)
+         << " # Files: "
+         << CurrentItems << " / " << TotalItems
+         << std::endl;
+   }
+
    double const DiffPercent = Percent - OldPercent;
    if (DiffPercent < 0.001 && _config->FindB("Acquire::Progress::Diffpercent", false) == true)
       return true;
@@ -1207,13 +1258,9 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
         snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
 
       // build the status str
-      status << "dlstatus:" << i
-             << ":"  << std::setprecision(3) << Percent
-             << ":" << msg
-             << endl;
-
-      std::string const dlstatus = status.str();
-      FileFd::Write(fd, dlstatus.c_str(), dlstatus.size());
+      std::string dlstatus;
+      strprintf(dlstatus, "dlstatus:%ld:%.4f:%s\n", i, Percent, msg);
+      FileFd::Write(fd, dlstatus.data(), dlstatus.size());
    }
 
    return true;