2007-11-30 18:49:53 +03:00
--- apt-0.5.15lorg2/tools/genpkglist.cc- 2007-11-30 15:26:23 +0300
+++ apt-0.5.15lorg2/tools/genpkglist.cc 2007-11-30 19:14:24 +0300
2007-08-11 20:01:05 +04:00
@@ -18,6 +18,8 @@
#include <map>
#include <iostream>
+#include <tr1/unordered_set>
+
#include <apt-pkg/error.h>
#include <apt-pkg/tagfile.h>
#include <apt-pkg/configuration.h>
2007-11-30 18:49:53 +03:00
@@ -77,115 +79,173 @@ typedef struct {
2007-08-11 20:01:05 +04:00
string url;
} UpdateInfo;
2007-10-08 22:33:47 +04:00
+// path-like Requires
+static
+std::tr1::unordered_set<std::string> reqfiles;
2007-08-11 20:01:05 +04:00
-static inline int usefullFile(char *a)
2007-10-08 22:33:47 +04:00
+static
+void addRequiredPath(const char *str)
2007-08-11 20:01:05 +04:00
{
- int l = strlen(a);
-
- if (strstr(a, "bin") || strstr(a, "/etc") || strncmp(a, "/lib", 4) == 0)
- return 1;
-
- if (l < 3)
- return 0;
2007-10-08 22:33:47 +04:00
+ reqfiles.insert(str);
+}
+
+static
+bool isRequiredPath(const char *dir, const char *basename)
+{
+ char fullname[strlen(dir) + strlen(basename) + 1];
+ strcpy(fullname, dir);
+ strcat(fullname, basename);
+ if (reqfiles.find(fullname) != reqfiles.end())
+ return true;
+ return false;
+}
+
+// atoms are constant strings with fixed address
+static
+std::tr1::unordered_set<std::string> atoms;
+
+static
+const char *atom(const char *str)
+{
+ return atoms.insert(str).first->c_str();
+}
+
+// memory-efficient way to map path -> packages:
+// dir -> <basename -> pkg+>
+typedef std::multimap<const char * /* basename */, const char * /* pkg */> BPM;
+static
+std::map<const char * /* dir */, BPM> pathOwners;
+
+typedef BPM::const_iterator BPI;
+
+static
+void addPathOwner(const char *dir, const char *basename, const char *pkg)
+{
+ BPM& bp = pathOwners[atom(dir)];
+ basename = atom(basename);
+ pkg = atom(pkg);
+ // check if pkg is already there
+ std::pair<BPI, BPI> ii = bp.equal_range(basename);
+ for (BPI i = ii.first; i != ii.second; ++i) {
+ if (i->second == pkg) {
+ //fprintf(stderr, "already: %s%s %s\n", dir, basename, pkg);
+ return;
+ }
+ }
+ bp.insert(std::make_pair(basename, pkg));
+}
+
+static
+int countPathOwners(const char *dir, const char *basename)
+{
+ BPM& bp = pathOwners[atom(dir)];
+ basename = atom(basename);
+ std::pair<BPI, BPI> ii = bp.equal_range(basename);
+ return std::distance(ii.first, ii.second);
+}
+
+static
+int usefulFile(const char *dir, const char *basename)
+{
+ // standard dirs
+ if (strstr(dir, "/bin/"))
+ return 1;
+ if (strstr(dir, "/sbin/"))
2007-08-11 20:01:05 +04:00
+ return 1;
+ if (strstr(dir, "/etc/"))
+ return 1;
- if (strcmp(a + l - 3, ".so") == 0
- || strstr(a, ".so."))
- return 1;
2007-10-08 22:33:47 +04:00
+ // libraries
2007-08-11 20:01:05 +04:00
+ const char *pos = strstr(basename, ".so");
+ if (pos > basename) {
+ int c = pos[3];
+ if (c == '.' || c == '\0')
+ return 1;
+ }
+
2007-10-08 22:33:47 +04:00
+ // if this path is required by any package, it is useful
+ if (isRequiredPath(dir, basename))
+ return 2;
+
+ // if the path is owned by two or more packages, it is still useful
+ if (countPathOwners(dir, basename) > 1)
+ return 3;
2007-08-11 20:01:05 +04:00
+
2007-10-08 22:33:47 +04:00
+ // other paths are not useful
2007-08-11 20:01:05 +04:00
return 0;
}
2007-11-30 18:49:53 +03:00
-static void copyStrippedFileList(Header header, Header newHeader)
+static
+void copyStrippedFileList(Header h1, Header h2)
{
- int i;
- int i1, i2;
-
- int type1, type2, type3;
- int count1, count2, count3;
- char **dirnames = NULL, **basenames = NULL;
- int_32 *dirindexes = NULL;
- char **dnames, **bnames;
- int_32 *dindexes;
- int res1, res2, res3;
-
-#define FREE(a) if (a) free(a);
-
- res1 = headerGetEntry(header, RPMTAG_DIRNAMES, &type1,
- (void**)&dirnames, &count1);
- res2 = headerGetEntry(header, RPMTAG_BASENAMES, &type2,
- (void**)&basenames, &count2);
- res3 = headerGetEntry(header, RPMTAG_DIRINDEXES, &type3,
- (void**)&dirindexes, &count3);
-
- if (res1 != 1 || res2 != 1 || res3 != 1) {
- FREE(dirnames);
- FREE(basenames);
+ int_32 bnt = 0, dnt = 0, dit = 0;
+ struct {
+ const char **bn, **dn;
+ int_32 *di;
+ int_32 bnc, dnc, dic;
+ } l1 = {0}, l2 = {0};
+
+ if (!headerGetEntry(h1, RPMTAG_BASENAMES, &bnt, (void**)&l1.bn, &l1.bnc))
+ return;
+ if (!headerGetEntry(h1, RPMTAG_DIRNAMES, &dnt, (void**)&l1.dn, &l1.dnc)) {
+ headerFreeData(l1.bn, (rpmTagType)bnt);
+ return;
+ }
+ if (!headerGetEntry(h1, RPMTAG_DIRINDEXES, &dit, (void**)&l1.di, &l1.dic)) {
+ headerFreeData(l1.bn, (rpmTagType)bnt);
+ headerFreeData(l1.dn, (rpmTagType)dnt);
return;
}
- dnames = dirnames;
- bnames = basenames;
- dindexes = (int_32*)malloc(sizeof(int_32)*count3);
-
- i1 = 0;
- i2 = 0;
- for (i = 0; i < count2 ; i++)
- {
2007-10-08 22:33:47 +04:00
- int ok = 0;
-
2007-08-11 20:01:05 +04:00
- ok = usefullFile(basenames[i]);
- if (!ok)
- ok = usefullFile(dirnames[dirindexes[i]]);
2007-11-23 13:52:00 +03:00
-
- if (!ok) {
- int k = i;
- while (dirindexes[i] == dirindexes[k] && i < count2)
- i++;
- i--;
- continue;
2007-11-30 18:49:53 +03:00
+ assert(l1.bnc == l1.dic);
+
+ for (int i = 0; i < l1.bnc; i++) {
+ const char *d = l1.dn[l1.di[i]], *b = l1.bn[i];
+ int ok = usefulFile(d, b);
+ // if (ok > 1) cerr << "useful(" << ok << "): " << d << b << std::endl;
+ if (ok < 1)
+ continue;
+
+ if (!l2.bn) {
+ l2.bn = new const char*[l1.bnc];
+ l2.dn = new const char*[l1.dnc];
+ l2.di = new int_32[l1.dic];
+ }
+
+ l2.bn[l2.bnc++] = b;
+
+ bool has_dir = false;
+ for (int j = 0; j < l2.dnc; j++) {
+ if (l2.dn[j] == d) {
+ l2.di[l2.dic++] = j;
+ has_dir = true;
+ break;
+ }
+ }
+ if (!has_dir) {
+ l2.dn[l2.dnc] = d;
+ l2.di[l2.dic++] = l2.dnc++;
}
2007-11-23 13:52:00 +03:00
-
-
2007-11-30 18:49:53 +03:00
- if (ok)
- {
- int j;
-
- bnames[i1] = basenames[i];
- for (j = 0; j < i2; j++)
- {
- if (dnames[j] == dirnames[dirindexes[i]])
- {
- dindexes[i1] = j;
- break;
- }
- }
- if (j == i2)
- {
- dnames[i2] = dirnames[dirindexes[i]];
- dindexes[i1] = i2;
- i2++;
- }
- assert(i2 <= count1);
- i1++;
- }
}
-
- if (i1 == 0) {
- FREE(dirnames);
- FREE(basenames);
- FREE(dindexes);
- return;
2007-11-23 13:52:00 +03:00
+
2007-11-30 18:49:53 +03:00
+ assert(l2.bnc == l2.dic);
+
+ if (l2.bnc > 0) {
+ headerAddEntry(h2, RPMTAG_BASENAMES, bnt, l2.bn, l2.bnc);
+ headerAddEntry(h2, RPMTAG_DIRNAMES, dnt, l2.dn, l2.dnc);
+ headerAddEntry(h2, RPMTAG_DIRINDEXES, dit, l2.di, l2.dic);
}
-
- headerAddEntry(newHeader, RPMTAG_DIRNAMES, type1, dnames, i2);
-
- headerAddEntry(newHeader, RPMTAG_BASENAMES, type2, bnames, i1);
-
- headerAddEntry(newHeader, RPMTAG_DIRINDEXES, type3, dindexes, i1);
-
- FREE(dirnames);
- FREE(basenames);
- FREE(dindexes);
+
+ if (l2.bn) {
+ delete[] l2.bn;
+ delete[] l2.dn;
+ delete[] l2.di;
+ }
+
+ headerFreeData(l1.bn, (rpmTagType)bnt);
+ headerFreeData(l1.dn, (rpmTagType)dnt);
+ headerFreeData(l1.di, (rpmTagType)dit);
}
@@ -599,6 +659,76 @@ int main(int argc, char ** argv)
2007-08-11 20:01:05 +04:00
int isSource;
#endif
+ if (!fullFileList) {
2007-10-08 22:33:47 +04:00
+ // ALT: file list cannot be stripped in a dumb manner -- this is going
+ // to produce unmet dependencies. First pass is required to initialize
+ // certain data structures.
2007-08-11 20:01:05 +04:00
+ for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
2007-08-11 21:51:14 +04:00
+ if (progressBar) {
+ if (entry_cur)
+ printf("\b\b\b\b\b\b\b\b\b\b");
+ printf(" %04i/%04i", entry_cur + 1, entry_no);
+ fflush(stdout);
+ }
+
2007-08-11 20:01:05 +04:00
+ fd = fdOpen(dirEntries[entry_cur]->d_name, O_RDONLY, 0666);
+ if (!fd)
+ continue;
+ int rc;
+ Header h;
+#if RPM_VERSION >= 0x040100
+ rc = rpmReadPackageFile(ts, fd, dirEntries[entry_cur]->d_name, &h);
+ if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY) {
+#else
+ rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
+ if (rc == 0) {
+#endif
2007-10-08 22:33:47 +04:00
+ // path-like Requires
+ int_32 reqtype = 0;
+ const char **requires = NULL;
+ int_32 nreq = 0;
2007-08-11 20:01:05 +04:00
+ rc = headerGetEntry(h, RPMTAG_REQUIRENAME, &reqtype, (void**)&requires, &nreq);
2007-08-11 21:51:14 +04:00
+ if (rc == 1) {
+ if (reqtype == RPM_STRING_ARRAY_TYPE) {
+ int i;
+ for (i = 0; i < nreq; i++) {
+ const char *req = requires[i];
+ if (*req == '/') {
+ // cerr << dirEntries[entry_cur]->d_name << " requires " << req << endl;
2007-10-08 22:33:47 +04:00
+ addRequiredPath(req);
2007-08-11 21:51:14 +04:00
+ }
2007-08-11 20:01:05 +04:00
+ }
+ }
+ }
2007-10-08 22:33:47 +04:00
+ headerFreeTag(h, requires, (rpmTagType)reqtype);
+
+ // path ownership
+ const char *pkg = NULL;
+ int_32 pkgt = 0;
+ const char **bn = NULL, **dn = NULL;
+ int_32 *di = NULL;
+ int_32 bnt = 0, dnt = 0, dit = 0;
+ int_32 bnc = 0;
+ rc = headerGetEntry(h, RPMTAG_NAME, &pkgt, (void**)&pkg, NULL)
+ && headerGetEntry(h, RPMTAG_BASENAMES, &bnt, (void**)&bn, &bnc)
+ && headerGetEntry(h, RPMTAG_DIRNAMES, &dnt, (void**)&dn, NULL)
+ && headerGetEntry(h, RPMTAG_DIRINDEXES, &dit, (void**)&di, NULL)
+ ;
+ if (rc == 1) {
+ int i;
+ for (i = 0; i < bnc; i++)
+ addPathOwner(dn[di[i]], bn[i], pkg);
+ }
+ headerFreeTag(h, pkg, (rpmTagType)pkgt);
+ headerFreeTag(h, bn, (rpmTagType)bnt);
+ headerFreeTag(h, dn, (rpmTagType)dnt);
+ headerFreeTag(h, di, (rpmTagType)dit);
+
2007-08-11 20:01:05 +04:00
+ headerFree(h);
+ }
+ Fclose(fd);
+ }
+ }
for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
struct stat sb;