Commit 1cd1c398 authored by David Kalnischkies's avatar David Kalnischkies
Browse files

* apt-pkg/contrib/fileutl.cc:

  - add a parent-guarded "mkdir -p" as CreateDirectory()
* apt-pkg/acquire.{cc,h}:
  - add a delayed constructor with Setup() for success reporting
  - check for and create directories in Setup if needed instead of
    error out unfriendly in the Constructor (Closes: #523920, #525783)
  - optional handle a lock file in Setup()
* cmdline/apt-get.cc:
  - remove the lock file handling and let Acquire take care of it instead
parent b3793d41
Loading
Loading
Loading
Loading
+66 −23
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>

#include <apti18n.h>

@@ -29,7 +30,6 @@
#include <dirent.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/stat.h>
									/*}}}*/

using namespace std;
@@ -37,32 +37,72 @@ using namespace std;
// Acquire::pkgAcquire - Constructor					/*{{{*/
// ---------------------------------------------------------------------
/* We grab some runtime state from the configuration space */
pkgAcquire::pkgAcquire(pkgAcquireStatus *Log) : Log(Log)
pkgAcquire::pkgAcquire() : Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0),
			   Debug(_config->FindB("Debug::pkgAcquire",false)),
			   Running(false), LockFD(-1)
{
   Queues = 0;
   Configs = 0;
   Workers = 0;
   ToFetch = 0;
   Running = false;
   
   string Mode = _config->Find("Acquire::Queue-Mode","host");
   string const Mode = _config->Find("Acquire::Queue-Mode","host");
   if (strcasecmp(Mode.c_str(),"host") == 0)
      QueueMode = QueueHost;
   if (strcasecmp(Mode.c_str(),"access") == 0)
      QueueMode = QueueAccess;
}
pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : Queues(0), Workers(0),
			   Configs(0), Log(Progress), ToFetch(0),
			   Debug(_config->FindB("Debug::pkgAcquire",false)),
			   Running(false), LockFD(-1)
{
   string const Mode = _config->Find("Acquire::Queue-Mode","host");
   if (strcasecmp(Mode.c_str(),"host") == 0)
      QueueMode = QueueHost;
   if (strcasecmp(Mode.c_str(),"access") == 0)
      QueueMode = QueueAccess;
   Setup(Progress, "");
}
									/*}}}*/
// Acquire::Setup - Delayed Constructor					/*{{{*/
// ---------------------------------------------------------------------
/* Do everything needed to be a complete Acquire object and report the
   success (or failure) back so the user knows that something is wrong… */
bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock)
{
   Log = Progress;

   // check for existence and possibly create auxiliary directories
   if (CheckDirectory(_config->FindDir("Dir::State"), _config->FindDir("Dir::State::lists") + "partial/") == false ||
	CheckDirectory(_config->FindDir("Dir::Cache"), _config->FindDir("Dir::Cache::Archives") + "partial/") == false)
      return false;

   Debug = _config->FindB("Debug::pkgAcquire",false);
   if (Lock.empty() == true || _config->FindB("Debug::NoLocking", false) == true)
      return true;

   // Lock the directory this acquire object will work in
   LockFD = GetLock(flCombine(Lock, "lock"));
   if (LockFD == -1)
      return _error->Error(_("Unable to lock directory %s"), Lock.c_str());

   // This is really a stupid place for this
   struct stat St;
   if (stat((_config->FindDir("Dir::State::lists") + "partial/").c_str(),&St) != 0 ||
       S_ISDIR(St.st_mode) == 0)
      _error->Error(_("Lists directory %spartial is missing."),
		    _config->FindDir("Dir::State::lists").c_str());
   if (stat((_config->FindDir("Dir::Cache::Archives") + "partial/").c_str(),&St) != 0 ||
       S_ISDIR(St.st_mode) == 0)
      _error->Error(_("Archive directory %spartial is missing."),
		    _config->FindDir("Dir::Cache::Archives").c_str());
   return true;
}
									/*}}}*/
// Acquire::CheckDirectory - ensure that the given directory exists	/*{{{*/
// ---------------------------------------------------------------------
/* a small wrapper around CreateDirectory to check if it exists and to
   remove the trailing "/apt/" from the parent directory if needed */
bool pkgAcquire::CheckDirectory(string const &Parent, string const &Path) const
{
   if (DirectoryExists(Path) == true)
      return true;

   size_t const len = Parent.size();
   if (len > 5 && Parent.find("/apt/", len - 6, 5) != len - 5)
   {
      if (CreateDirectory(Parent.substr(0,len-5), Path) == true)
	 return true;
   }
   else if (CreateDirectory(Parent, Path) == true)
      return true;

   return _error->Errno("Acquire", _("Directory %s can't be created."), Path.c_str());
}
									/*}}}*/
// Acquire::~pkgAcquire	- Destructor					/*{{{*/
@@ -72,6 +112,9 @@ pkgAcquire::~pkgAcquire()
{
   Shutdown();

   if (LockFD != -1)
      close(LockFD);

   while (Configs != 0)
   {
      MethodConfig *Jnk = Configs;
+26 −5
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@
#ifndef PKGLIB_ACQUIRE_H
#define PKGLIB_ACQUIRE_H

#include <apt-pkg/macros.h>

#include <vector>
#include <string>

@@ -161,7 +163,7 @@ class pkgAcquire
     QueueAccess} QueueMode;

   /** \brief If \b true, debugging information will be dumped to std::clog. */
   bool Debug;
   bool const Debug;
   /** \brief If \b true, a download is currently in progress. */
   bool Running;

@@ -332,15 +334,22 @@ class pkgAcquire
    */
   double PartialPresent();

   /** \brief Construct a new pkgAcquire.
   /** \brief Delayed constructor
    *
    *  \param Log The progress indicator associated with this
    *  download, or \b NULL for none.  This object is not owned by the
    *  \param Progress indicator associated with this download or
    *  \b NULL for none.  This object is not owned by the
    *  download process and will not be deleted when the pkgAcquire
    *  object is destroyed.  Naturally, it should live for at least as
    *  long as the pkgAcquire object does.
    *  \param Lock defines a lock file that should be acquired to ensure
    *  only one Acquire class is in action at the time or an empty string
    *  if no lock file should be used.
    */
   pkgAcquire(pkgAcquireStatus *Log = 0);
   bool Setup(pkgAcquireStatus *Progress = NULL, string const &Lock = "");

   /** \brief Construct a new pkgAcquire. */
   pkgAcquire(pkgAcquireStatus *Log) __deprecated;
   pkgAcquire();

   /** \brief Destroy this pkgAcquire object.
    *
@@ -348,6 +357,18 @@ class pkgAcquire
    *  this download.
    */
   virtual ~pkgAcquire();

   private:
   /** \brief FD of the Lock file we acquire in Setup (if any) */
   int LockFD;

   /** \brief Ensure the existence of the given Path
    *
    *  \param Parent directory of the Path directory - a trailing
    *  /apt/ will be removed before CreateDirectory call.
    *  \param Path which should exist after (successful) call
    */
   bool CheckDirectory(string const &Parent, string const &Path) const;
};

/** \brief Represents a single download source from which an item
+3 −1
Original line number Diff line number Diff line
@@ -1398,7 +1398,9 @@ bool ListUpdate(pkgAcquireStatus &Stat,
		int PulseInterval)
{
   pkgAcquire::RunResult res;
   pkgAcquire Fetcher(&Stat);
   pkgAcquire Fetcher;
   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
      return false;

   // Populate it with the source selection
   if (List.GetIndexes(&Fetcher) == false)
+52 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
									/*}}}*/
// Include Files							/*{{{*/
#include <apt-pkg/fileutl.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/configuration.h>
@@ -197,6 +198,57 @@ bool FileExists(string File)
   return true;
}
									/*}}}*/
// DirectoryExists - Check if a directory exists and is really one	/*{{{*/
// ---------------------------------------------------------------------
/* */
bool DirectoryExists(string const &Path)
{
   struct stat Buf;
   if (stat(Path.c_str(),&Buf) != 0)
      return false;
   return ((Buf.st_mode & S_IFDIR) != 0);
}
									/*}}}*/
// CreateDirectory - poor man's mkdir -p guarded by a parent directory	/*{{{*/
// ---------------------------------------------------------------------
/* This method will create all directories needed for path in good old
   mkdir -p style but refuses to do this if Parent is not a prefix of
   this Path. Example: /var/cache/ and /var/cache/apt/archives are given,
   so it will create apt/archives if /var/cache exists - on the other
   hand if the parent is /var/lib the creation will fail as this path
   is not a parent of the path to be generated. */
bool CreateDirectory(string const &Parent, string const &Path)
{
   if (Parent.empty() == true || Path.empty() == true)
      return false;

   if (DirectoryExists(Path) == true)
      return true;

   if (DirectoryExists(Parent) == false)
      return false;

   // we are not going to create directories "into the blue"
   if (Path.find(Parent, 0) != 0)
      return false;

   vector<string> const dirs = VectorizeString(Path.substr(Parent.size()), '/');
   string progress = Parent;
   for (vector<string>::const_iterator d = dirs.begin(); d != dirs.end(); ++d)
   {
      if (d->empty() == true)
	 continue;

      progress.append("/").append(*d);
      if (DirectoryExists(progress) == true)
	 continue;

      if (mkdir(progress.c_str(), 0755) != 0)
	 return false;
   }
   return true;
}
									/*}}}*/
// GetListOfFilesInDir - returns a vector of files in the given dir	/*{{{*/
// ---------------------------------------------------------------------
/* If an extension is given only files with this extension are included
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#ifndef PKGLIB_FILEUTL_H
#define PKGLIB_FILEUTL_H

#include <apt-pkg/macros.h>

#include <string>
#include <vector>
@@ -82,6 +83,8 @@ bool RunScripts(const char *Cnf);
bool CopyFile(FileFd &From,FileFd &To);
int GetLock(string File,bool Errors = true);
bool FileExists(string File);
bool DirectoryExists(string const &Path) __attrib_const;
bool CreateDirectory(string const &Parent, string const &Path);
std::vector<string> GetListOfFilesInDir(string const &Dir, string const &Ext,
					bool const &SortList, bool const &AllowNoExt=false);
std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> const &Ext,
Loading