From d4af23c2d81116b8f7557ee795059bca126ae9f4 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sat, 26 Jun 2010 20:56:44 +0200 Subject: * apt-pkg/deb/deblistparser.cc: - Handle architecture wildcards (Closes: #547724). --- apt-pkg/deb/deblistparser.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 83c5b8d2e..ddbd0d31a 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -19,6 +19,7 @@ #include #include +#include #include /*}}}*/ @@ -572,8 +573,15 @@ 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(), arch.c_str(), 0) == 0) + Found = true; + else if (fnmatch(wildcard.c_str(), ("linux-" + arch).c_str(), 0) == 0) + Found = true; + } if (*End++ == ']') { I = End; -- cgit v1.2.3-70-g09d2 From 3b20aef1a2b5fd2fcd6f62a819edbdb19631fb98 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sat, 26 Jun 2010 23:01:49 +0200 Subject: apt-pkg/deb/deblistparser.cc: Fix bug in architecture wildcard support. Previously, linux-any was always matched, because the code simply appended linux- to the APT::Architecture value. Now, it does this only if the APT::Architecture value does not contain "-". --- apt-pkg/deb/deblistparser.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index ddbd0d31a..00016679a 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -473,6 +473,14 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) return I; } +/* + * CompleteArch: + * + * The complete architecture, consisting of -. + */ +static string CompleteArch(std::string& arch) { + return (arch.find("-") != string::npos) ? arch : "linux-" + arch; +} /*}}}*/ // ListParser::ParseDepends - Parse a dependency element /*{{{*/ // --------------------------------------------------------------------- @@ -546,6 +554,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 == '[') @@ -577,9 +586,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, Found = true; } else { std::string wildcard = SubstVar(string(I, End), "any", "*"); - if (fnmatch(wildcard.c_str(), arch.c_str(), 0) == 0) - Found = true; - else if (fnmatch(wildcard.c_str(), ("linux-" + arch).c_str(), 0) == 0) + if (fnmatch(wildcard.c_str(), completeArch.c_str(), 0) == 0) Found = true; } -- cgit v1.2.3-70-g09d2 From 5143f361005775e3674f4f5871ad574cbe8ef705 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 27 Jun 2010 21:04:53 +0200 Subject: deblistparser: Special-case *-armel, lpia and powerpcspe architectures. --- apt-pkg/deb/deblistparser.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 00016679a..6ede14c4d 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -479,6 +479,12 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) * The complete architecture, consisting of -. */ 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; } /*}}}*/ -- cgit v1.2.3-70-g09d2 From ae4a4f91e90fb09a8de1699f18f3b28d095c4d73 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 28 Jun 2010 17:21:14 +0200 Subject: * apt-pkg/versionmatch.cc: - Support matching pins by regular expressions or glob() like patterns, regular expressions have to be put between to slashes; for example, /.*/. --- apt-pkg/versionmatch.cc | 58 +++++++++++++++++++++++++++++++++++++++---------- apt-pkg/versionmatch.h | 2 ++ debian/changelog | 4 ++++ 3 files changed, 52 insertions(+), 12 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index e5f0fafd2..72c9bff2d 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -18,6 +18,10 @@ #include #include +#include +#include +#include + /*}}}*/ // VersionMatch::pkgVersionMatch - Constructor /*{{{*/ @@ -162,6 +166,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) +{ + std::cerr << "MATCH " << pattern; + 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) { + std::cerr << "E: Invalid regular expression: " << regex << "\n"; + } else if (regexec(&preg, string, 0, NULL, 0) == 0) { + res = true; + } + free(regex); + 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 +219,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 +257,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); diff --git a/debian/changelog b/debian/changelog index 105936177..659facb37 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,10 @@ apt (0.7.26~exp8) experimental; urgency=low - Handle different logins on the same server (Closes: #586904). * apt-pkg/deb/deblistparser.cc: - Handle architecture wildcards (Closes: #547724). + * apt-pkg/versionmatch.cc: + - Support matching pins by regular expressions or glob() like patterns, + regular expressions have to be put between to slashes; for example, + /.*/. -- Julian Andres Klode Thu, 24 Jun 2010 10:56:39 +0200 -- cgit v1.2.3-70-g09d2 From 05002864535069dbc35fd1c713ab072a5b6df65f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 28 Jun 2010 17:29:11 +0200 Subject: Also support regular expressions and glob() patterns in "Pin: version". --- apt-pkg/versionmatch.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 72c9bff2d..2abb73e8d 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -155,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; } -- cgit v1.2.3-70-g09d2 From 01934fb1fe79cddcc3cb4c79c99c3c30390fdef6 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 28 Jun 2010 17:30:40 +0200 Subject: Remove debugging stuff, this was not meant to be here. --- apt-pkg/versionmatch.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 2abb73e8d..65908f733 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -175,7 +175,6 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) { - std::cerr << "MATCH " << pattern; if (pattern[0] == '/') { bool res = false; size_t length = strlen(pattern); -- cgit v1.2.3-70-g09d2 From 4213f040ac8464d8826b64746c49c21c53a1ab12 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 28 Jun 2010 17:34:54 +0200 Subject: Use _error->Warning() instead of writing to std::cerr. --- apt-pkg/versionmatch.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 65908f733..a269338d6 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -183,7 +183,7 @@ bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) char *regex = strdup(pattern + 1); regex[length - 2] = '\0'; if (regcomp(&preg, regex, REG_EXTENDED | REG_ICASE) != 0) { - std::cerr << "E: Invalid regular expression: " << regex << "\n"; + _error->Warning("Invalid regular expression: %s", regex); } else if (regexec(&preg, string, 0, NULL, 0) == 0) { res = true; } -- cgit v1.2.3-70-g09d2 From cec9f4f4bb39cc075acded3478d59d0f17d3ed89 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 28 Jun 2010 17:38:08 +0200 Subject: Also free regular expressions. --- apt-pkg/versionmatch.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'apt-pkg') diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index a269338d6..093180f9b 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -188,6 +188,7 @@ bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) res = true; } free(regex); + regfree(&preg); return res; } } -- cgit v1.2.3-70-g09d2 From 3010fb0e069d2fd4c7a6ade4559bfb659bf8f2fb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 29 Jun 2010 17:23:24 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - Make FileFd replace files atomically in WriteTemp mode (for cache, etc). --- apt-pkg/contrib/fileutl.cc | 20 +++++++++++++++----- apt-pkg/contrib/fileutl.h | 3 ++- debian/changelog | 2 ++ 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 16f7ce929..0b0739cda 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -654,10 +655,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; } @@ -839,11 +841,19 @@ bool FileFd::Close() if (iFd >= 0 && close(iFd) != 0) Res &= _error->Errno("close",_("Problem closing the file")); iFd = -1; - + + if ((Flags & Replace) == Replace) { + FileName = TemporaryFileName; // for the unlink() below. + if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) + Res &= _error->Errno("rename",_("Problem renaming the file")); + } + 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/debian/changelog b/debian/changelog index 3a0fcd83d..1bf6815a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,8 @@ apt (0.7.26~exp8) experimental; urgency=low - Support matching pins by regular expressions or glob() like patterns, regular expressions have to be put between to slashes; for example, /.*/. + * apt-pkg/contrib/fileutl.cc: + - Make FileFd replace files atomically in WriteTemp mode (for cache, etc). * debian/control: - Set Standards-Version to 3.9.0 -- cgit v1.2.3-70-g09d2 From fd3b761e8cba6ed626639b50b1221246098c7b3a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 29 Jun 2010 17:28:33 +0200 Subject: Fix the atomic replace. --- apt-pkg/contrib/fileutl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0b0739cda..0b62d1bd8 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -843,9 +843,9 @@ bool FileFd::Close() iFd = -1; if ((Flags & Replace) == Replace) { - FileName = TemporaryFileName; // for the unlink() below. 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 && -- cgit v1.2.3-70-g09d2