summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib/fileutl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib/fileutl.cc')
-rw-r--r--apt-pkg/contrib/fileutl.cc91
1 files changed, 77 insertions, 14 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 0d2d3f356..49b2f3828 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -19,6 +19,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>
@@ -27,6 +28,7 @@
#include <cstdlib>
#include <cstring>
+#include <cstdio>
#include <iostream>
#include <unistd.h>
@@ -198,16 +200,62 @@ 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
in the returned vector, otherwise every "normal" file is included. */
std::vector<string> GetListOfFilesInDir(string const &Dir, string const &Ext,
- bool const &SortList)
-{
- return GetListOfFilesInDir(Dir, Ext, SortList, false);
-}
-std::vector<string> GetListOfFilesInDir(string const &Dir, string const &Ext,
bool const &SortList, bool const &AllowNoExt)
{
std::vector<string> ext;
@@ -235,6 +283,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
}
std::vector<string> List;
+ Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently");
DIR *D = opendir(Dir.c_str());
if (D == 0)
{
@@ -260,6 +309,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
{
if (Debug == true)
std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl;
+ _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str());
continue;
}
}
@@ -267,6 +317,8 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
{
if (Debug == true)
std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl;
+ if (SilentIgnore.Match(Ent->d_name) == false)
+ _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str());
continue;
}
}
@@ -619,10 +671,11 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms)
case WriteEmpty:
{
- struct stat Buf;
- if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
- unlink(FileName.c_str());
- iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
+ Flags |= Replace;
+ char *name = strdup((FileName + ".XXXXXX").c_str());
+ TemporaryFileName = string(mktemp(name));
+ iFd = open(TemporaryFileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
+ free(name);
break;
}
@@ -829,21 +882,31 @@ bool FileFd::Close()
if ((Flags & AutoClose) == AutoClose)
{
if (gz != NULL) {
- int e = gzclose(gz);
+ int const e = gzclose(gz);
// gzdopen() 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"));
+ Res &= _error->Errno("close",_("Problem closing the gzip file %s"), FileName.c_str());
} else
if (iFd > 0 && close(iFd) != 0)
- Res &= _error->Errno("close",_("Problem closing the file"));
+ Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
}
+
+ if ((Flags & Replace) == Replace && iFd >= 0) {
+ 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());
+
+ FileName = TemporaryFileName; // for the unlink() below.
+ }
+
iFd = -1;
gz = NULL;
-
+
if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
FileName.empty() == false)
if (unlink(FileName.c_str()) != 0)
- Res &= _error->WarningE("unlnk",_("Problem unlinking the file"));
+ Res &= _error->WarningE("unlnk",_("Problem unlinking the file %s"), FileName.c_str());
+
+
return Res;
}
/*}}}*/