summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/cmndline.cc42
-rw-r--r--apt-pkg/contrib/cmndline.h1
-rw-r--r--apt-pkg/contrib/configuration.cc24
-rw-r--r--apt-pkg/contrib/configuration.h37
-rw-r--r--apt-pkg/contrib/error.h8
-rw-r--r--apt-pkg/contrib/fileutl.cc57
-rw-r--r--apt-pkg/contrib/fileutl.h8
-rw-r--r--apt-pkg/contrib/macros.h34
-rw-r--r--apt-pkg/contrib/mmap.cc197
-rw-r--r--apt-pkg/contrib/mmap.h15
-rw-r--r--apt-pkg/contrib/strutl.cc88
-rw-r--r--apt-pkg/contrib/strutl.h23
-rw-r--r--apt-pkg/contrib/weakptr.h62
13 files changed, 437 insertions, 159 deletions
diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc
index bfd53695e..0b16bf51a 100644
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -135,7 +135,9 @@ bool CommandLine::Parse(int argc,const char **argv)
for (; I != argc; I++)
*Files++ = argv[I];
*Files = 0;
-
+
+ SaveInConfig(argc, argv);
+
return true;
}
/*}}}*/
@@ -351,3 +353,41 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
return false;
}
/*}}}*/
+// CommandLine::SaveInConfig - for output later in a logfile or so /*{{{*/
+// ---------------------------------------------------------------------
+/* We save the commandline here to have it around later for e.g. logging.
+ It feels a bit like a hack here and isn't bulletproof, but it is better
+ than nothing after all. */
+void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
+{
+ char cmdline[300];
+ unsigned int length = 0;
+ bool lastWasOption = false;
+ bool closeQuote = false;
+ for (unsigned int i = 0; i < argc; ++i, ++length)
+ {
+ for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length)
+ {
+ cmdline[length] = argv[i][j];
+ if (lastWasOption == true && argv[i][j] == '=')
+ {
+ // That is possibly an option: Quote it if it includes spaces,
+ // the benefit is that this will eliminate also most false positives
+ const char* c = &argv[i][j+1];
+ for (; *c != '\0' && *c != ' '; ++c);
+ if (*c == '\0') continue;
+ cmdline[++length] = '"';
+ closeQuote = true;
+ }
+ }
+ if (closeQuote == true)
+ cmdline[length++] = '"';
+ // Problem: detects also --hello
+ if (cmdline[length-1] == 'o')
+ lastWasOption = true;
+ cmdline[length] = ' ';
+ }
+ cmdline[--length] = '\0';
+ _config->Set("CommandLine::AsString", cmdline);
+}
+ /*}}}*/
diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h
index e28071e81..7c0c71aa7 100644
--- a/apt-pkg/contrib/cmndline.h
+++ b/apt-pkg/contrib/cmndline.h
@@ -60,6 +60,7 @@ class CommandLine
Configuration *Conf;
bool HandleOpt(int &I,int argc,const char *argv[],
const char *&Opt,Args *A,bool PreceedeMatch = false);
+ void static SaveInConfig(unsigned int const &argc, char const * const * const argv);
public:
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 8e3b84499..9129d92f0 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -79,7 +79,7 @@ Configuration::~Configuration()
/* This will lookup a single item by name below another item. It is a
helper function for the main lookup function */
Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
- unsigned long Len,bool Create)
+ unsigned long const &Len,bool const &Create)
{
int Res = 1;
Item *I = Head->Child;
@@ -112,7 +112,7 @@ Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
// ---------------------------------------------------------------------
/* This performs a fully scoped lookup of a given name, possibly creating
new items */
-Configuration::Item *Configuration::Lookup(const char *Name,bool Create)
+Configuration::Item *Configuration::Lookup(const char *Name,bool const &Create)
{
if (Name == 0)
return Root->Child;
@@ -239,7 +239,7 @@ vector<string> Configuration::FindVector(const char *Name) const
// Configuration::FindI - Find an integer value /*{{{*/
// ---------------------------------------------------------------------
/* */
-int Configuration::FindI(const char *Name,int Default) const
+int Configuration::FindI(const char *Name,int const &Default) const
{
const Item *Itm = Lookup(Name);
if (Itm == 0 || Itm->Value.empty() == true)
@@ -256,7 +256,7 @@ int Configuration::FindI(const char *Name,int Default) const
// Configuration::FindB - Find a boolean type /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool Configuration::FindB(const char *Name,bool Default) const
+bool Configuration::FindB(const char *Name,bool const &Default) const
{
const Item *Itm = Lookup(Name);
if (Itm == 0 || Itm->Value.empty() == true)
@@ -332,7 +332,7 @@ void Configuration::Set(const char *Name,const string &Value)
// Configuration::Set - Set an integer value /*{{{*/
// ---------------------------------------------------------------------
/* */
-void Configuration::Set(const char *Name,int Value)
+void Configuration::Set(const char *Name,int const &Value)
{
Item *Itm = Lookup(Name,true);
if (Itm == 0)
@@ -345,7 +345,7 @@ void Configuration::Set(const char *Name,int Value)
// Configuration::Clear - Clear an single value from a list /*{{{*/
// ---------------------------------------------------------------------
/* */
-void Configuration::Clear(const string Name, int Value)
+void Configuration::Clear(string const &Name, int const &Value)
{
char S[300];
snprintf(S,sizeof(S),"%i",Value);
@@ -355,7 +355,7 @@ void Configuration::Clear(const string Name, int Value)
// Configuration::Clear - Clear an single value from a list /*{{{*/
// ---------------------------------------------------------------------
/* */
-void Configuration::Clear(const string Name, string Value)
+void Configuration::Clear(string const &Name, string const &Value)
{
Item *Top = Lookup(Name.c_str(),false);
if (Top == 0 || Top->Child == 0)
@@ -386,7 +386,7 @@ void Configuration::Clear(const string Name, string Value)
// Configuration::Clear - Clear an entire tree /*{{{*/
// ---------------------------------------------------------------------
/* */
-void Configuration::Clear(string Name)
+void Configuration::Clear(string const &Name)
{
Item *Top = Lookup(Name.c_str(),false);
if (Top == 0)
@@ -501,8 +501,8 @@ string Configuration::Item::FullTag(const Item *Stop) const
sections like 'zone "foo.org" { .. };' This causes each section to be
added in with a tag like "zone::foo.org" instead of being split
tag/value. AsSectional enables Sectional parsing.*/
-bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
- unsigned Depth)
+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);
@@ -773,6 +773,8 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
else
return _error->Error(_("Syntax error %s:%u: Unsupported directive '%s'"),FName.c_str(),CurLine,Tag.c_str());
}
+ else if (Tag.empty() == true && NoWord == false && Word == "#clear")
+ return _error->Error(_("Syntax error %s:%u: clear directive requires an option tree as argument"),FName.c_str(),CurLine);
else
{
// Set the item in the configuration class
@@ -830,7 +832,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
// ---------------------------------------------------------------------
/* */
bool ReadConfigDir(Configuration &Conf,const string &Dir,
- bool AsSectional, unsigned Depth)
+ bool const &AsSectional, unsigned const &Depth)
{
vector<string> const List = GetListOfFilesInDir(Dir, "conf", true, true);
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index e2da83f5b..2494c1d7c 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -58,8 +58,8 @@ class Configuration
Item *Root;
bool ToFree;
- Item *Lookup(Item *Head,const char *S,unsigned long Len,bool Create);
- Item *Lookup(const char *Name,bool Create);
+ 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
{
return ((Configuration *)this)->Lookup(Name,false);
@@ -68,32 +68,33 @@ class Configuration
public:
string Find(const char *Name,const char *Default = 0) const;
- string Find(const string Name,const char *Default = 0) const {return Find(Name.c_str(),Default);};
+ string Find(string const &Name,const char *Default = 0) const {return Find(Name.c_str(),Default);};
+ string Find(string const &Name, string const &Default) const {return Find(Name.c_str(),Default.c_str());};
string FindFile(const char *Name,const char *Default = 0) const;
string FindDir(const char *Name,const char *Default = 0) const;
- std::vector<string> FindVector(const string &Name) const;
+ std::vector<string> FindVector(string const &Name) const;
std::vector<string> FindVector(const char *Name) const;
- int FindI(const char *Name,int Default = 0) const;
- int FindI(const string Name,int Default = 0) const {return FindI(Name.c_str(),Default);};
- bool FindB(const char *Name,bool Default = false) const;
- bool FindB(const string Name,bool Default = false) const {return FindB(Name.c_str(),Default);};
+ int FindI(const char *Name,int const &Default = 0) const;
+ int FindI(string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);};
+ bool FindB(const char *Name,bool const &Default = false) const;
+ bool FindB(string const &Name,bool const &Default = false) const {return FindB(Name.c_str(),Default);};
string FindAny(const char *Name,const char *Default = 0) const;
- inline void Set(const string Name,string Value) {Set(Name.c_str(),Value);};
+ inline void Set(const string &Name,const string &Value) {Set(Name.c_str(),Value);};
void CndSet(const char *Name,const string &Value);
void Set(const char *Name,const string &Value);
- void Set(const char *Name,int Value);
+ void Set(const char *Name,const int &Value);
- inline bool Exists(const string Name) const {return Exists(Name.c_str());};
+ inline bool Exists(const string &Name) const {return Exists(Name.c_str());};
bool Exists(const char *Name) const;
bool ExistsAny(const char *Name) const;
// clear a whole tree
- void Clear(const string Name);
+ void Clear(const string &Name);
// remove a certain value from a list (e.g. the list of "APT::Keep-Fds")
- void Clear(const string List, string Value);
- void Clear(const string List, int Value);
+ void Clear(string const &List, string const &Value);
+ void Clear(string const &List, int const &Value);
inline const Item *Tree(const char *Name) const {return Lookup(Name);};
@@ -108,11 +109,11 @@ class Configuration
extern Configuration *_config;
bool ReadConfigFile(Configuration &Conf,const string &FName,
- bool AsSectional = false,
- unsigned Depth = 0);
+ bool const &AsSectional = false,
+ unsigned const &Depth = 0);
bool ReadConfigDir(Configuration &Conf,const string &Dir,
- bool AsSectional = false,
- unsigned Depth = 0);
+ bool const &AsSectional = false,
+ unsigned const &Depth = 0);
#endif
diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h
index 90747ff7e..8d5ec05ea 100644
--- a/apt-pkg/contrib/error.h
+++ b/apt-pkg/contrib/error.h
@@ -60,13 +60,13 @@ class GlobalError
public:
// Call to generate an error from a library call.
- bool Errno(const char *Function,const char *Description,...) __like_printf_2 __cold;
- bool WarningE(const char *Function,const char *Description,...) __like_printf_2 __cold;
+ bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
+ bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
/* A warning should be considered less severe than an error, and may be
ignored by the client. */
- bool Error(const char *Description,...) __like_printf_1 __cold;
- bool Warning(const char *Description,...) __like_printf_1 __cold;
+ bool Error(const char *Description,...) __like_printf(2) __cold;
+ bool Warning(const char *Description,...) __like_printf(2) __cold;
// Simple accessors
inline bool PendingError() {return PendingFlag;};
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index da32983f1..16f7ce929 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -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,16 +198,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;
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 85a94898c..003bd9b83 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -21,6 +21,7 @@
#ifndef PKGLIB_FILEUTL_H
#define PKGLIB_FILEUTL_H
+#include <apt-pkg/macros.h>
#include <string>
#include <vector>
@@ -82,11 +83,10 @@ bool RunScripts(const char *Cnf);
bool CopyFile(FileFd &From,FileFd &To);
int GetLock(string File,bool Errors = true);
bool FileExists(string File);
-// FIXME: next ABI-Break: merge the two method-headers
+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);
-std::vector<string> GetListOfFilesInDir(string const &Dir, string const &Ext,
- bool const &SortList, bool const &AllowNoExt);
+ bool const &SortList, bool const &AllowNoExt=false);
std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> const &Ext,
bool const &SortList);
string SafeGetCWD();
diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h
index 9aeb77b81..62e7b65db 100644
--- a/apt-pkg/contrib/macros.h
+++ b/apt-pkg/contrib/macros.h
@@ -56,33 +56,35 @@
// some nice optional GNUC features
#if __GNUC__ >= 3
- #define __must_check __attribute__ ((warn_unused_result))
- #define __deprecated __attribute__ ((deprecated))
- /* likely() and unlikely() can be used to mark boolean expressions
- as (not) likely true which will help the compiler to optimise */
- #define likely(x) __builtin_expect (!!(x), 1)
- #define unlikely(x) __builtin_expect (!!(x), 0)
+ #define __must_check __attribute__ ((warn_unused_result))
+ #define __deprecated __attribute__ ((deprecated))
+ #define __attrib_const __attribute__ ((__const__))
+ /* likely() and unlikely() can be used to mark boolean expressions
+ as (not) likely true which will help the compiler to optimise */
+ #define likely(x) __builtin_expect (!!(x), 1)
+ #define unlikely(x) __builtin_expect (!!(x), 0)
#else
- #define __must_check /* no warn_unused_result */
- #define __deprecated /* no deprecated */
- #define likely(x) (x)
- #define unlikely(x) (x)
+ #define __must_check /* no warn_unused_result */
+ #define __deprecated /* no deprecated */
+ #define __attrib_const /* no const attribute */
+ #define likely(x) (x)
+ #define unlikely(x) (x)
#endif
// cold functions are unlikely() to be called
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
- #define __cold __attribute__ ((__cold__))
+ #define __cold __attribute__ ((__cold__))
+ #define __hot __attribute__ ((__hot__))
#else
- #define __cold /* no cold marker */
+ #define __cold /* no cold marker */
+ #define __hot /* no hot marker */
#endif
#ifdef __GNUG__
// Methods have a hidden this parameter that is visible to this attribute
- #define __like_printf_1 __attribute__ ((format (printf, 2, 3)))
- #define __like_printf_2 __attribute__ ((format (printf, 3, 4)))
+ #define __like_printf(n) __attribute__((format(printf, n, n + 1)))
#else
- #define __like_printf_1
- #define __like_printf_2
+ #define __like_printf(n) /* no like-printf */
#endif
#endif
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index 4d5fcf71e..d233e51bc 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
+#include <errno.h>
#include <cstring>
/*}}}*/
@@ -35,7 +36,7 @@
// ---------------------------------------------------------------------
/* */
MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
- Base(0)
+ Base(0), SyncToFd(NULL)
{
if ((Flags & NoImmMap) != NoImmMap)
Map(F);
@@ -45,7 +46,7 @@ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
// ---------------------------------------------------------------------
/* */
MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
- Base(0)
+ Base(0), SyncToFd(NULL)
{
}
/*}}}*/
@@ -78,7 +79,24 @@ bool MMap::Map(FileFd &Fd)
// Map it.
Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
if (Base == (void *)-1)
- return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize);
+ {
+ if (errno == ENODEV || errno == EINVAL)
+ {
+ // The filesystem doesn't support this particular kind of mmap.
+ // So we allocate a buffer and read the whole file into it.
+ int const dupped_fd = dup(Fd.Fd());
+ if (dupped_fd == -1)
+ return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd());
+
+ Base = new unsigned char[iSize];
+ SyncToFd = new FileFd (dupped_fd);
+ if (!SyncToFd->Seek(0L) || !SyncToFd->Read(Base, iSize))
+ return false;
+ }
+ else
+ return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),
+ iSize);
+ }
return true;
}
@@ -93,10 +111,19 @@ bool MMap::Close(bool DoSync)
if (DoSync == true)
Sync();
-
- if (munmap((char *)Base,iSize) != 0)
- _error->Warning("Unable to munmap");
-
+
+ if (SyncToFd != NULL)
+ {
+ delete[] (char *)Base;
+ delete SyncToFd;
+ SyncToFd = NULL;
+ }
+ else
+ {
+ if (munmap((char *)Base, iSize) != 0)
+ _error->WarningE("mmap", _("Unable to close mmap"));
+ }
+
iSize = 0;
Base = 0;
return true;
@@ -113,8 +140,18 @@ bool MMap::Sync()
#ifdef _POSIX_SYNCHRONIZED_IO
if ((Flags & ReadOnly) != ReadOnly)
- if (msync((char *)Base,iSize,MS_SYNC) < 0)
- return _error->Errno("msync","Unable to write mmap");
+ {
+ if (SyncToFd != NULL)
+ {
+ if (!SyncToFd->Seek(0) || !SyncToFd->Write(Base, iSize))
+ return false;
+ }
+ else
+ {
+ if (msync((char *)Base, iSize, MS_SYNC) < 0)
+ return _error->Errno("msync", _("Unable to synchronize mmap"));
+ }
+ }
#endif
return true;
}
@@ -130,8 +167,19 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
#ifdef _POSIX_SYNCHRONIZED_IO
unsigned long PSize = sysconf(_SC_PAGESIZE);
if ((Flags & ReadOnly) != ReadOnly)
- if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0)
- return _error->Errno("msync","Unable to write mmap");
+ {
+ if (SyncToFd != 0)
+ {
+ if (!SyncToFd->Seek(0) ||
+ !SyncToFd->Write (((char *)Base)+Start, Stop-Start))
+ return false;
+ }
+ else
+ {
+ if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0)
+ return _error->Errno("msync", _("Unable to synchronize mmap"));
+ }
+ }
#endif
return true;
}
@@ -140,8 +188,10 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
// DynamicMMap::DynamicMMap - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
- MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
+DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Workspace,
+ unsigned long const &Grow, unsigned long const &Limit) :
+ MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(Workspace),
+ GrowFactor(Grow), Limit(Limit)
{
if (_error->PendingError() == true)
return;
@@ -165,32 +215,48 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace)
/* We try here to use mmap to reserve some space - this is much more
cooler than the fallback solution to simply allocate a char array
and could come in handy later than we are able to grow such an mmap */
-DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
- MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
+DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace,
+ unsigned long const &Grow, unsigned long const &Limit) :
+ MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace),
+ GrowFactor(Grow), Limit(Limit)
{
- if (_error->PendingError() == true)
- return;
+ if (_error->PendingError() == true)
+ return;
+
+ // disable Moveable if we don't grow
+ if (Grow == 0)
+ Flags &= ~Moveable;
+
+#ifndef __linux__
+ // kfreebsd doesn't have mremap, so we use the fallback
+ if ((Flags & Moveable) == Moveable)
+ Flags |= Fallback;
+#endif
#ifdef _POSIX_MAPPED_FILES
- // Set the permissions.
- int Prot = PROT_READ;
- int Map = MAP_PRIVATE | MAP_ANONYMOUS;
- if ((Flags & ReadOnly) != ReadOnly)
- Prot |= PROT_WRITE;
- if ((Flags & Public) == Public)
- Map = MAP_SHARED | MAP_ANONYMOUS;
+ if ((Flags & Fallback) != Fallback) {
+ // Set the permissions.
+ int Prot = PROT_READ;
+ int Map = MAP_PRIVATE | MAP_ANONYMOUS;
+ if ((Flags & ReadOnly) != ReadOnly)
+ Prot |= PROT_WRITE;
+ if ((Flags & Public) == Public)
+ Map = MAP_SHARED | MAP_ANONYMOUS;
- // use anonymous mmap() to get the memory
- Base = (unsigned char*) mmap(0, WorkSpace, Prot, Map, -1, 0);
+ // use anonymous mmap() to get the memory
+ Base = (unsigned char*) mmap(0, WorkSpace, Prot, Map, -1, 0);
- if(Base == MAP_FAILED)
- _error->Errno("DynamicMMap",_("Couldn't make mmap of %lu bytes"),WorkSpace);
-#else
- // fallback to a static allocated space
- Base = new unsigned char[WorkSpace];
- memset(Base,0,WorkSpace);
+ if(Base == MAP_FAILED)
+ _error->Errno("DynamicMMap",_("Couldn't make mmap of %lu bytes"),WorkSpace);
+
+ iSize = 0;
+ return;
+ }
#endif
- iSize = 0;
+ // fallback to a static allocated space
+ Base = new unsigned char[WorkSpace];
+ memset(Base,0,WorkSpace);
+ iSize = 0;
}
/*}}}*/
// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
@@ -311,30 +377,55 @@ unsigned long DynamicMMap::WriteString(const char *String,
/*}}}*/
// DynamicMMap::Grow - Grow the mmap /*{{{*/
// ---------------------------------------------------------------------
-/* This method will try to grow the mmap we currently use. This doesn't
- work most of the time because we can't move the mmap around in the
- memory for now as this would require to adjust quite a lot of pointers
- but why we should not at least try to grow it before we give up? */
-bool DynamicMMap::Grow()
-{
-#if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
- unsigned long newSize = WorkSpace + 1024*1024;
+/* This method is a wrapper around different methods to (try to) grow
+ a mmap (or our char[]-fallback). Encounterable environments:
+ 1. Moveable + !Fallback + linux -> mremap with MREMAP_MAYMOVE
+ 2. Moveable + !Fallback + !linux -> not possible (forbidden by constructor)
+ 3. Moveable + Fallback -> realloc
+ 4. !Moveable + !Fallback + linux -> mremap alone - which will fail in 99,9%
+ 5. !Moveable + !Fallback + !linux -> not possible (forbidden by constructor)
+ 6. !Moveable + Fallback -> not possible
+ [ While Moveable and Fallback stands for the equally named flags and
+ "linux" indicates a linux kernel instead of a freebsd kernel. ]
+ So what you can see here is, that a MMAP which want to be growable need
+ to be moveable to have a real chance but that this method will at least try
+ the nearly impossible 4 to grow it before it finally give up: Never say never. */
+bool DynamicMMap::Grow() {
+ if (Limit != 0 && WorkSpace >= Limit)
+ return _error->Error(_("Unable to increase the size of the MMap as the "
+ "limit of %lu bytes is already reached."), Limit);
- if(Fd != 0)
- {
- Fd->Seek(newSize - 1);
- char C = 0;
- Fd->Write(&C,sizeof(C));
- }
+ unsigned long const newSize = WorkSpace + 1024*1024;
- Base = mremap(Base, WorkSpace, newSize, 0);
- if(Base == MAP_FAILED)
- return false;
+ if(Fd != 0) {
+ Fd->Seek(newSize - 1);
+ char C = 0;
+ Fd->Write(&C,sizeof(C));
+ }
+ if ((Flags & Fallback) != Fallback) {
+#if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
+ #ifdef MREMAP_MAYMOVE
+ if ((Flags & Moveable) == Moveable)
+ Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
+ else
+ #endif
+ Base = mremap(Base, WorkSpace, newSize, 0);
- WorkSpace = newSize;
- return true;
+ if(Base == MAP_FAILED)
+ return false;
#else
- return false;
+ return false;
#endif
+ } else {
+ if ((Flags & Moveable) != Moveable)
+ return false;
+
+ Base = realloc(Base, newSize);
+ if (Base == NULL)
+ return false;
+ }
+
+ WorkSpace = newSize;
+ return true;
}
/*}}}*/
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index bde62217d..5ca951204 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -44,13 +44,18 @@ class MMap
unsigned long iSize;
void *Base;
+ // In case mmap can not be used, we keep a dup of the file
+ // descriptor that should have been mmaped so that we can write to
+ // the file in Sync().
+ FileFd *SyncToFd;
+
bool Map(FileFd &Fd);
bool Close(bool DoSync = true);
public:
enum OpenFlags {NoImmMap = (1<<0),Public = (1<<1),ReadOnly = (1<<2),
- UnMapped = (1<<3)};
+ UnMapped = (1<<3), Moveable = (1<<4), Fallback = (1 << 5)};
// Simple accessors
inline operator void *() {return Base;};
@@ -82,6 +87,8 @@ class DynamicMMap : public MMap
FileFd *Fd;
unsigned long WorkSpace;
+ unsigned long const GrowFactor;
+ unsigned long const Limit;
Pool *Pools;
unsigned int PoolCount;
@@ -96,8 +103,10 @@ class DynamicMMap : public MMap
inline unsigned long WriteString(const string &S) {return WriteString(S.c_str(),S.length());};
void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;};
- DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace = 2*1024*1024);
- DynamicMMap(unsigned long Flags,unsigned long WorkSpace = 2*1024*1024);
+ DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &WorkSpace = 2*1024*1024,
+ unsigned long const &Grow = 1024*1024, unsigned long const &Limit = 0);
+ DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace = 2*1024*1024,
+ unsigned long const &Grow = 1024*1024, unsigned long const &Limit = 0);
virtual ~DynamicMMap();
};
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 8e8820949..c7d63ce8a 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -198,7 +198,8 @@ bool ParseQuoteWord(const char *&String,string &Res)
char *I;
for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
{
- if (*Start == '%' && Start + 2 < C)
+ if (*Start == '%' && Start + 2 < C &&
+ isxdigit(Start[1]) && isxdigit(Start[2]))
{
Tmp[0] = Start[1];
Tmp[1] = Start[2];
@@ -273,7 +274,8 @@ string QuoteString(const string &Str, const char *Bad)
for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
{
if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
- *I <= 0x20 || *I >= 0x7F)
+ *I == 0x25 || // percent '%' char
+ *I <= 0x20 || *I >= 0x7F) // control chars
{
char Buf[10];
sprintf(Buf,"%%%02x",(int)*I);
@@ -290,10 +292,16 @@ string QuoteString(const string &Str, const char *Bad)
/* This undoes QuoteString */
string DeQuoteString(const string &Str)
{
+ return DeQuoteString(Str.begin(),Str.end());
+}
+string DeQuoteString(string::const_iterator const &begin,
+ string::const_iterator const &end)
+{
string Res;
- for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
+ for (string::const_iterator I = begin; I != end; I++)
{
- if (*I == '%' && I + 2 < Str.end())
+ if (*I == '%' && I + 2 < end &&
+ isxdigit(I[1]) && isxdigit(I[2]))
{
char Tmp[3];
Tmp[0] = I[1];
@@ -566,7 +574,7 @@ int stringcmp(string::const_iterator A,string::const_iterator AEnd,
int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
{
for (; A != AEnd && B != BEnd; A++, B++)
- if (toupper(*A) != toupper(*B))
+ if (tolower_ascii(*A) != tolower_ascii(*B))
break;
if (A == AEnd && B == BEnd)
@@ -575,7 +583,7 @@ int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
return 1;
if (B == BEnd)
return -1;
- if (toupper(*A) < toupper(*B))
+ if (tolower_ascii(*A) < tolower_ascii(*B))
return -1;
return 1;
}
@@ -584,7 +592,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
const char *B,const char *BEnd)
{
for (; A != AEnd && B != BEnd; A++, B++)
- if (toupper(*A) != toupper(*B))
+ if (tolower_ascii(*A) != tolower_ascii(*B))
break;
if (A == AEnd && B == BEnd)
@@ -593,7 +601,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
return 1;
if (B == BEnd)
return -1;
- if (toupper(*A) < toupper(*B))
+ if (tolower_ascii(*A) < tolower_ascii(*B))
return -1;
return 1;
}
@@ -601,7 +609,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
string::const_iterator B,string::const_iterator BEnd)
{
for (; A != AEnd && B != BEnd; A++, B++)
- if (toupper(*A) != toupper(*B))
+ if (tolower_ascii(*A) != tolower_ascii(*B))
break;
if (A == AEnd && B == BEnd)
@@ -610,7 +618,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
return 1;
if (B == BEnd)
return -1;
- if (toupper(*A) < toupper(*B))
+ if (tolower_ascii(*A) < tolower_ascii(*B))
return -1;
return 1;
}
@@ -789,28 +797,28 @@ bool ReadMessages(int Fd, vector<string> &List)
// MonthConv - Converts a month string into a number /*{{{*/
// ---------------------------------------------------------------------
/* This was lifted from the boa webserver which lifted it from 'wn-v1.07'
- Made it a bit more robust with a few touppers though. */
+ Made it a bit more robust with a few tolower_ascii though. */
static int MonthConv(char *Month)
{
- switch (toupper(*Month))
+ switch (tolower_ascii(*Month))
{
- case 'A':
- return toupper(Month[1]) == 'P'?3:7;
- case 'D':
+ case 'a':
+ return tolower_ascii(Month[1]) == 'p'?3:7;
+ case 'd':
return 11;
- case 'F':
+ case 'f':
return 1;
- case 'J':
- if (toupper(Month[1]) == 'A')
+ case 'j':
+ if (tolower_ascii(Month[1]) == 'a')
return 0;
- return toupper(Month[2]) == 'N'?5:6;
- case 'M':
- return toupper(Month[2]) == 'R'?2:4;
- case 'N':
+ return tolower_ascii(Month[2]) == 'n'?5:6;
+ case 'm':
+ return tolower_ascii(Month[2]) == 'r'?2:4;
+ case 'n':
return 10;
- case 'O':
+ case 'o':
return 9;
- case 'S':
+ case 's':
return 8;
// Pretend it is January..
@@ -1000,6 +1008,24 @@ bool TokSplitString(char Tok,char *Input,char **List,
return true;
}
/*}}}*/
+// VectorizeString - Split a string up into a vector of strings /*{{{*/
+// ---------------------------------------------------------------------
+/* This can be used to split a given string up into a vector, so the
+ propose is the same as in the method above and this one is a bit slower
+ also, but the advantage is that we have an iteratable vector */
+vector<string> VectorizeString(string const &haystack, char const &split)
+{
+ string::const_iterator start = haystack.begin();
+ string::const_iterator end = start;
+ vector<string> exploded;
+ do {
+ for (; end != haystack.end() && *end != split; ++end);
+ exploded.push_back(string(start, end));
+ start = end + 1;
+ } while (end != haystack.end() && (++end) != haystack.end());
+ return exploded;
+}
+ /*}}}*/
// RegexChoice - Simple regex list/list matcher /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -1115,10 +1141,13 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
// tolower_ascii - tolower() function that ignores the locale /*{{{*/
// ---------------------------------------------------------------------
-/* */
-int tolower_ascii(int c)
+/* This little function is the most called method we have and tries
+ therefore to do the absolut minimum - and is noteable faster than
+ standard tolower/toupper and as a bonus avoids problems with different
+ locales - we only operate on ascii chars anyway. */
+int tolower_ascii(int const c)
{
- if (c >= 'A' and c <= 'Z')
+ if (c >= 'A' && c <= 'Z')
return c + 32;
return c;
}
@@ -1217,9 +1246,10 @@ void URI::CopyFrom(const string &U)
else
{
Host.assign(At+1,SingleSlash);
- User.assign(FirstColon,SecondColon);
+ // username and password must be encoded (RFC 3986)
+ User.assign(DeQuoteString(FirstColon,SecondColon));
if (SecondColon < At)
- Password.assign(SecondColon+1,At);
+ Password.assign(DeQuoteString(SecondColon+1,At));
}
// Now we parse the RFC 2732 [] hostnames.
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index a1e7f3934..e509145f9 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -25,19 +25,12 @@
#include <iostream>
#include <time.h>
+#include "macros.h"
+
using std::string;
using std::vector;
using std::ostream;
-#ifdef __GNUG__
-// Methods have a hidden this parameter that is visible to this attribute
-#define APT_FORMAT2 __attribute__ ((format (printf, 2, 3)))
-#define APT_FORMAT3 __attribute__ ((format (printf, 3, 4)))
-#else
-#define APT_FORMAT2
-#define APT_FORMAT3
-#endif
-
bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest);
char *_strstrip(char *String);
char *_strtabexpand(char *String,size_t Len);
@@ -45,6 +38,7 @@ bool ParseQuoteWord(const char *&String,string &Res);
bool ParseCWord(const char *&String,string &Res);
string QuoteString(const string &Str,const char *Bad);
string DeQuoteString(const string &Str);
+string DeQuoteString(string::const_iterator const &begin, string::const_iterator const &end);
string SizeToStr(double Bytes);
string TimeToStr(unsigned long Sec);
string Base64Encode(const string &Str);
@@ -59,11 +53,12 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0)
bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
bool TokSplitString(char Tok,char *Input,char **List,
unsigned long ListMax);
-void ioprintf(ostream &out,const char *format,...) APT_FORMAT2;
-void strprintf(string &out,const char *format,...) APT_FORMAT2;
-char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3;
+vector<string> VectorizeString(string const &haystack, char const &split) __attrib_const;
+void ioprintf(ostream &out,const char *format,...) __like_printf(2);
+void strprintf(string &out,const char *format,...) __like_printf(2);
+char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3);
bool CheckDomainList(const string &Host, const string &List);
-int tolower_ascii(int c);
+int tolower_ascii(int const c) __attrib_const __hot;
#define APT_MKSTRCMP(name,func) \
inline int name(const char *A,const char *B) {return func(A,A+strlen(A),B,B+strlen(B));}; \
@@ -143,6 +138,4 @@ struct RxChoiceList
unsigned long RegexChoice(RxChoiceList *Rxs,const char **ListBegin,
const char **ListEnd);
-#undef APT_FORMAT2
-
#endif
diff --git a/apt-pkg/contrib/weakptr.h b/apt-pkg/contrib/weakptr.h
new file mode 100644
index 000000000..5158e393c
--- /dev/null
+++ b/apt-pkg/contrib/weakptr.h
@@ -0,0 +1,62 @@
+/* weakptr.h - An object which supports weak pointers.
+ *
+ * Copyright (C) 2010 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef WEAK_POINTER_H
+#define WEAK_POINTER_H
+
+#include <set>
+/**
+ * Class for objects providing support for weak pointers.
+ *
+ * This class allows for the registration of certain pointers as weak,
+ * which will cause them to be set to NULL when the destructor of the
+ * object is called.
+ */
+class WeakPointable {
+private:
+ std::set<WeakPointable**> pointers;
+
+public:
+
+ /**
+ * Add a new weak pointer.
+ */
+ inline void AddWeakPointer(WeakPointable** weakptr) {
+ pointers.insert(weakptr);
+ }
+
+ /**
+ * Remove the weak pointer from the list of weak pointers.
+ */
+ inline void RemoveWeakPointer(WeakPointable **weakptr) {
+ pointers.erase(weakptr);
+ }
+
+ /**
+ * Deconstruct the object, set all weak pointers to NULL.
+ */
+ ~WeakPointable() {
+ std::set<WeakPointable**>::iterator iter = pointers.begin();
+ while (iter != pointers.end())
+ **(iter++) = NULL;
+ }
+};
+
+#endif // WEAK_POINTER_H