Subject: Finding non-pkgsrc files with pkg_admin
To: None <tech-pkg@netbsd.org>
From: Peter Bex <Peter.Bex@student.kun.nl>
List: tech-pkg
Date: 04/17/2005 19:31:28
--5CUMAwwhRxlRszMD
Content-Type: multipart/mixed; boundary="2qXFWqzzG3v1+95a"
Content-Disposition: inline


--2qXFWqzzG3v1+95a
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hello all,

I just created a little patch for pkg_admin which allows you to find files
in a certain tree which don't belong to any package.  This is useful for
sysadmins to remove cruft that stays after buggy PLISTS, mistakes they made
themselves and probably some other situations I haven't thought of yet.

It already helped me find some left-over files of some pkgsrc-wip
experimentation, which I forgot to remove after changing an installation-pa=
th
in the package.

There is a problem, though.  I currently scan a specified subtree for files
and search pkgdb.byfile.db for the file.  There are files which are install=
ed
by pkgsrc, but which are not recorded in pkgdb.byfile.db.

Here's an example.  The pkg firefox-gtk2 installs this file:
/usr/pkg/lib/firefox-gtk2/chrome/overlayinfo/inspector/content/overlays.rdf

This is recorded in +CONTENTS:
+CONTENTS:@unexec /bin/rm %D/lib/firefox-gtk2/chrome/overlayinfo/inspector/=
content/overlays.rdf

pkg_info -L firefox-gtk2 | grep overlays.rdf  returns nothing

(yes, I know this is an old pkg, but it applies to other packages as well)

So, I am thinking... isn't this really a bug?  The file certainly is instal=
led
by pkgsrc.  So pkg_info should at least show it.

Since it's a _file_ installed by pkgsrc, pkgdb.byFILE.db should also record=
 it.

I would really like this pkg_admin feature to work.  It would help pkgsrc
developers tremendously with debugging PLIST issues, too.

I attached the patch in case someone wants to take a look at the code.

Please include me in the CC when you reply, I'm not a subscriber to tech-pk=
g.

Regards,
Peter
--=20
http://www.student.kun.nl/peter.bex
--
"The process of preparing programs for a digital computer
 is especially attractive, not only because it can be economically
 and scientifically rewarding, but also because it can be an aesthetic
 experience much like composing poetry or music."
							-- Donald Knuth

--2qXFWqzzG3v1+95a
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="main.c.diff"
Content-Transfer-Encoding: quoted-printable

Index: main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.sbin/pkg_install/admin/main.c,v
retrieving revision 1.43
diff -u -r1.43 main.c
--- main.c	15 Jan 2004 09:33:38 -0000	1.43
+++ main.c	17 Apr 2005 15:43:02 -0000
@@ -409,7 +409,66 @@
 	return 0;
 }
=20
-int=20
+static int
+is_pkg_file(const char *filename)
+{
+	return (pkgdb_retrieve(filename) !=3D NULL);
+}
+
+static void
+find_free(const char *basepath, const char *cwd)
+{
+	DIR *dp;
+	struct dirent *de;
+
+	dp =3D opendir(".");
+	if (dp =3D=3D NULL)
+		err(EXIT_FAILURE, "opendir failed");
+	while ((de =3D readdir(dp)) !=3D NULL) {
+		int len;
+		char *fullname;
+
+		if (strcmp(de->d_name, ".") =3D=3D 0 ||
+		    strcmp(de->d_name, "..") =3D=3D 0)
+			continue;
+
+		if (cwd !=3D NULL)
+			len =3D strlen(cwd) + strlen(basepath) + 3;
+		else
+			len =3D strlen(basepath) + 2;
+		fullname =3D malloc(len + strlen(de->d_name));
+		if (cwd !=3D NULL) {
+			strcpy(fullname, basepath);
+			strcat(fullname, "/");
+			strcat(fullname, cwd);
+			strcat(fullname, "/");
+		} else {
+			strcpy(fullname, basepath);
+			strcat(fullname, "/");
+		}
+		strcat(fullname, de->d_name);
+
+		if (isdir(de->d_name)) {
+			if (chdir(de->d_name) =3D=3D -1)
+				err(EXIT_FAILURE, "cannot chdir to %s", de->d_name);
+			find_free(basepath, (fullname + strlen(basepath) + 1));
+			fchdir(dirfd(dp));
+		} else {
+			/*
+			 * We can't check for directories, since those are
+			 * not listed in pkgdb.byfile.db :(
+			 */
+			if (!is_pkg_file(fullname))
+				printf("%s\n", fullname);
+		}
+
+
+		free(fullname);
+	}
+	closedir(dp);
+}
+
+int
 main(int argc, char *argv[])
 {
 	const char	*prog;
@@ -633,6 +692,32 @@
=20
 		close(saved_wd);
=20
+	} else if (strcasecmp(argv[0], "lsfree") =3D=3D 0) {
+
+		int i;
+		char cwd[MAXPATHLEN];
+
+		if (argc < 2)
+			usage(prog);
+
+		if (!pkgdb_open(ReadOnly))
+			err(EXIT_FAILURE, "cannot open pkgdb");
+
+		for (i =3D 1; argv[i] !=3D NULL; ++i) {
+			getcwd(cwd, MAXPATHLEN);
+			if (chdir(argv[i]) =3D=3D -1)
+				err(EXIT_FAILURE, "cannot chdir to %s",argv[i]);
+			find_free(argv[i], NULL);
+			chdir(cwd);
+		}
+
+		pkgdb_close();
+
+	} else if (strcasecmp(argv[0], "delfree") =3D=3D 0) {
+
+		/* Delete free files */
+		/* find_free(getenv("PKG_PATH"), FREE_DELETE); */
+
 	} else if (strcasecmp(argv[0], "list") =3D=3D 0 ||
 	    strcasecmp(argv[0], "dump") =3D=3D 0) {
=20

--2qXFWqzzG3v1+95a--

--5CUMAwwhRxlRszMD
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (NetBSD)

iD8DBQFCYp1wLg33BXzVMqsRAug1AJ93gYZ9jPrLB/kaeu2hAbMezUs+uQCeO8pf
xyLwbvf+ht6Ab+DsVbGUDcM=
=QzmT
-----END PGP SIGNATURE-----

--5CUMAwwhRxlRszMD--