diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 20 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.h | 3 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 23 | ||||
-rw-r--r-- | apt-pkg/versionmatch.cc | 60 | ||||
-rw-r--r-- | apt-pkg/versionmatch.h | 2 |
5 files changed, 89 insertions, 19 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index e95ddf562..62d42e4da 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -27,6 +27,7 @@ #include <cstdlib> #include <cstring> +#include <cstdio> #include <iostream> #include <unistd.h> @@ -658,10 +659,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; } @@ -843,11 +845,19 @@ bool FileFd::Close() if (iFd >= 0 && close(iFd) != 0) Res &= _error->Errno("close",_("Problem closing the file")); iFd = -1; - + + if ((Flags & Replace) == Replace) { + if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) + Res &= _error->Errno("rename",_("Problem renaming the file")); + FileName = TemporaryFileName; // for the unlink() below. + } + if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && FileName.empty() == false) if (unlink(FileName.c_str()) != 0) Res &= _error->WarningE("unlnk",_("Problem unlinking the file")); + + return Res; } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 003bd9b83..528725f89 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -34,9 +34,10 @@ class FileFd int iFd; enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2), - HitEof = (1<<3)}; + HitEof = (1<<3), Replace = (1<<4) }; unsigned long Flags; string FileName; + string TemporaryFileName; public: enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp}; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index d1931f909..24df57a5c 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -19,6 +19,7 @@ #include <apt-pkg/md5.h> #include <apt-pkg/macros.h> +#include <fnmatch.h> #include <ctype.h> /*}}}*/ @@ -473,6 +474,20 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) return I; } +/* + * CompleteArch: + * + * The complete architecture, consisting of <kernel>-<cpu>. + */ +static string CompleteArch(std::string& arch) { + if (arch == "armel") return "linux-arm"; + if (arch == "lpia") return "linux-i386"; + if (arch == "powerpcspe") return "linux-powerpc"; + if (arch == "uclibc-linux-armel") return "linux-arm"; + if (arch == "uclinux-armel") return "uclinux-arm"; + + return (arch.find("-") != string::npos) ? arch : "linux-" + arch; +} /*}}}*/ // ListParser::ParseDepends - Parse a dependency element /*{{{*/ // --------------------------------------------------------------------- @@ -546,6 +561,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, if (ParseArchFlags == true) { string arch = _config->Find("APT::Architecture"); + string completeArch = CompleteArch(arch); // Parse an architecture if (I != Stop && *I == '[') @@ -573,8 +589,13 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, I++; } - if (stringcmp(arch,I,End) == 0) + if (stringcmp(arch,I,End) == 0) { Found = true; + } else { + std::string wildcard = SubstVar(string(I, End), "any", "*"); + if (fnmatch(wildcard.c_str(), completeArch.c_str(), 0) == 0) + Found = true; + } if (*End++ == ']') { I = End; diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index e5f0fafd2..093180f9b 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -18,6 +18,10 @@ #include <stdio.h> #include <ctype.h> +#include <fnmatch.h> +#include <sys/types.h> +#include <regex.h> + /*}}}*/ // VersionMatch::pkgVersionMatch - Constructor /*{{{*/ @@ -151,6 +155,8 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) { if (MatchVer(Ver.VerStr(),VerStr,VerPrefixMatch) == true) return Ver; + if (ExpressionMatches(VerStr, Ver.VerStr()) == true) + return Ver; continue; } @@ -162,6 +168,36 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) // This will be Ended by now. return Ver; } + +#ifndef FNM_CASEFOLD +#define FNM_CASEFOLD 0 +#endif + +bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) +{ + if (pattern[0] == '/') { + bool res = false; + size_t length = strlen(pattern); + if (pattern[length - 1] == '/') { + regex_t preg; + char *regex = strdup(pattern + 1); + regex[length - 2] = '\0'; + if (regcomp(&preg, regex, REG_EXTENDED | REG_ICASE) != 0) { + _error->Warning("Invalid regular expression: %s", regex); + } else if (regexec(&preg, string, 0, NULL, 0) == 0) { + res = true; + } + free(regex); + regfree(&preg); + return res; + } + } + return fnmatch(pattern, string, FNM_CASEFOLD) == 0; +} +bool pkgVersionMatch::ExpressionMatches(const std::string& pattern, const char *string) +{ + return ExpressionMatches(pattern.c_str(), string); +} /*}}}*/ // VersionMatch::FileMatch - Match against an index file /*{{{*/ // --------------------------------------------------------------------- @@ -185,37 +221,37 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (RelVerStr.empty() == false) if (File->Version == 0 || - MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false) + (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false && + ExpressionMatches(RelVerStr, File.Version()) == false)) return false; if (RelOrigin.empty() == false) - if (File->Origin == 0 || - stringcasecmp(RelOrigin,File.Origin()) != 0) + if (File->Origin == 0 || !ExpressionMatches(RelOrigin,File.Origin())) return false; if (RelArchive.empty() == false) if (File->Archive == 0 || - stringcasecmp(RelArchive,File.Archive()) != 0) + !ExpressionMatches(RelArchive,File.Archive())) return false; if (RelCodename.empty() == false) if (File->Codename == 0 || - stringcasecmp(RelCodename,File.Codename()) != 0) + !ExpressionMatches(RelCodename,File.Codename())) return false; if (RelRelease.empty() == false) if ((File->Archive == 0 || - stringcasecmp(RelRelease,File.Archive()) != 0) && + !ExpressionMatches(RelRelease,File.Archive())) && (File->Codename == 0 || - stringcasecmp(RelRelease,File.Codename()) != 0)) + !ExpressionMatches(RelRelease,File.Codename()))) return false; if (RelLabel.empty() == false) if (File->Label == 0 || - stringcasecmp(RelLabel,File.Label()) != 0) + !ExpressionMatches(RelLabel,File.Label())) return false; if (RelComponent.empty() == false) if (File->Component == 0 || - stringcasecmp(RelComponent,File.Component()) != 0) + !ExpressionMatches(RelComponent,File.Component())) return false; if (RelArchitecture.empty() == false) if (File->Architecture == 0 || - stringcasecmp(RelArchitecture,File.Architecture()) != 0) + !ExpressionMatches(RelArchitecture,File.Architecture())) return false; return true; } @@ -223,12 +259,12 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (Type == Origin) { if (OrSite.empty() == false) { - if (File->Site == 0 || OrSite != File.Site()) + if (File->Site == 0 || !ExpressionMatches(OrSite, File.Site())) return false; } else // so we are talking about file:// or status file if (strcmp(File.Site(),"") == 0 && File->Archive != 0) // skip the status file return false; - return (OrSite == File.Site()); /* both strings match */ + return (ExpressionMatches(OrSite, File.Site())); /* both strings match */ } return false; diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h index a8da072ae..39639a23d 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -67,6 +67,8 @@ class pkgVersionMatch enum MatchType {None = 0,Version,Release,Origin} Type; bool MatchVer(const char *A,string B,bool Prefix); + bool ExpressionMatches(const char *pattern, const char *string); + bool ExpressionMatches(const std::string& pattern, const char *string); bool FileMatch(pkgCache::PkgFileIterator File); pkgCache::VerIterator Find(pkgCache::PkgIterator Pkg); |