bin/77082: src/usr.sbin/pkg_install - Add 3 new macros to clean pkg-plist

Florent Thoumie flz at xbsd.org
Thu Feb 3 15:50:21 PST 2005


>Number:         77082
>Category:       bin
>Synopsis:       src/usr.sbin/pkg_install - Add 3 new macros to clean pkg-plist
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 03 23:50:20 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Florent Thoumie
>Release:        FreeBSD 5.3-RELEASE i386
>Organization:
Xbsd.org
>Environment:

System: FreeBSD gate.xbsd.org 5.3-RELEASE FreeBSD 5.3-RELEASE #2: Wed Nov 24 16:35:34 CET 2004 root at gate.xbsd.org:/usr/src/sys/i386/compile/GATE i386

>Description:

Rationale:

Packing lists are clobbered with lines like :

@exec [ ! -f %B/foo ] && cp %B/%f %B/foo
@unexec cmp -s %D/etc/foo %D/etc/foo-dist && rm %D/etc/foo
@unexec rmdir %D/share/foo 2> /dev/null || true

This patch introduces 3 new macros :

@dirrmie name : remove directory if empty, actually just don't bother with error messages
when trying to remove the directory.
@cpin name : copy if non-existent, copy name from name-dist if name doesn't exist yet.
@rmiu name : remove if unchanged, remove name if name and name-dist are no different.

A simple port is attached to test these new macros.

>How-To-Repeat:
	
>Fix:

	

--- pkg_install.diff begins here ---
diff -ruN src/usr.sbin/pkg_install/add/extract.c src/usr.sbin/pkg_install.new/add/extract.c
--- src/usr.sbin/pkg_install/add/extract.c	Wed Jul 28 09:19:15 2004
+++ src/usr.sbin/pkg_install.new/add/extract.c	Fri Feb  4 00:00:35 2005
@@ -137,6 +137,7 @@
     /* Do it */
     while (p) {
 	char cmd[FILENAME_MAX];
+	char tmp[FILENAME_MAX], tmp2[FILENAME_MAX];
 
 	switch(p->type) {
 	case PLIST_NAME:
@@ -266,6 +267,25 @@
 
 	case PLIST_IGNORE:
 	    p = p->next;
+	    break;
+
+	case PLIST_CPIN:
+	    sprintf(tmp, "%s/%s", Directory, p->name);
+	    sprintf(tmp2, "%s/%s-dist", Directory, p->name);
+	    PUSHOUT(Directory);
+	    if (!fexists(tmp2)) {
+		warnx("file '%s' does not exist!\n"
+	"this packing list is incorrect - ignoring delete request", tmp2);
+	    }
+	    else if (!fexists(tmp)) {
+		if (Verbose)
+		    printf("Installing '%s' in '%s' (non-existent)\n", tmp2, tmp);
+		if (!Fake && vsystem("cp %s %s", tmp2, tmp)) {
+		    errx(2, "%s: unable to copy '%s' to '%s'", __func__, p->name,
+			    tmp2, tmp);
+		}
+	    }
+	    last_file = p->name;
 	    break;
 
 	default:
diff -ruN src/usr.sbin/pkg_install/create/pkg_create.1 src/usr.sbin/pkg_install.new/create/pkg_create.1
--- src/usr.sbin/pkg_install/create/pkg_create.1	Sat Jul  3 01:12:52 2004
+++ src/usr.sbin/pkg_install.new/create/pkg_create.1	Fri Feb  4 00:00:35 2005
@@ -504,6 +504,29 @@
 The
 .Pa name
 directory will not be removed unless it is empty.
+.It Cm @dirrmie Ar name
+Same as
+.Cm @dirrm ,
+but there will be no error message nor warning if the directory is not
+empty.
+.It Cm @cpin Ar name
+Declare file
+.Pa name
+to be copied from file
+.Pa name-dist
+if it does not exist yet.
+.Cm @cpin
+stands for copy if non-existent.
+.It Cm @rmiu Ar name
+Declare file
+.Pa name
+to be deleted at deinstall time. Note that this file will only be deleted
+if it is the same file as
+.Pa name-dist.
+.Cm @rmiu
+(which stands for remove if unchanged) is intended to be used in conjonction
+with
+.Cm @cpin .
 .It Cm @mtree Ar name
 Declare
 .Pa name
diff -ruN src/usr.sbin/pkg_install/delete/pkg_delete.1 src/usr.sbin/pkg_install.new/delete/pkg_delete.1
--- src/usr.sbin/pkg_install/delete/pkg_delete.1	Sat Jul  3 01:12:52 2004
+++ src/usr.sbin/pkg_install.new/delete/pkg_delete.1	Fri Feb  4 00:00:35 2005
@@ -60,6 +60,9 @@
 .Cm @mode
 (check for setuid),
 .Cm @dirrm ,
+.Cm @dirrmie ,
+.Cm @cpin ,
+.Cm @rmiu ,
 .Cm @exec ,
 and
 .Cm @unexec
diff -ruN src/usr.sbin/pkg_install/info/show.c src/usr.sbin/pkg_install.new/info/show.c
--- src/usr.sbin/pkg_install/info/show.c	Mon May 26 19:06:05 2003
+++ src/usr.sbin/pkg_install.new/info/show.c	Fri Feb  4 00:00:35 2005
@@ -179,6 +179,18 @@
 	    printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
 	    break;
 
+	case PLIST_DIR_RMIE:
+	    printf(Quiet ? "@dirrmie %s\n" : "\tDeinstall directory remove if empty: %s\n", p->name);
+	    break;
+
+	case PLIST_RMIU:
+	    printf(Quiet ? "@rmiu %s\n" : "\tFile (removed if unchanged): %s\n", p->name);
+	    break;
+
+	case PLIST_CPIN:
+	    printf(Quiet ? "@cpin %s\n" : "\tFile (copied if non-existent): %s\n", p->name);
+	    break;
+
 	case PLIST_OPTION:
 	    printf(Quiet ? "@option %s\n" :
 		"\tOption \"%s\" controlling package installation behaviour\n",
diff -ruN src/usr.sbin/pkg_install/lib/file.c src/usr.sbin/pkg_install.new/lib/file.c
--- src/usr.sbin/pkg_install/lib/file.c	Wed Jul 28 18:03:13 2004
+++ src/usr.sbin/pkg_install.new/lib/file.c	Fri Feb  4 00:00:35 2005
@@ -113,6 +113,20 @@
     return FALSE;
 }
 
+/*
+ * Returns 0 if the two files are the same, 1 if they are different and
+ * other values and another value if an error occured.
+ */
+int
+isdifferent(const char *fname, const char *sname)
+{
+    char cmd[FILENAME_MAX];
+    if (!fname || !sname)
+	return FALSE;
+    snprintf(cmd, FILENAME_MAX, "/usr/bin/cmp -s %s %s", fname, sname);
+    return vsystem(cmd);
+}
+
 /* Returns TRUE if file is a URL specification */
 Boolean
 isURL(const char *fname)
diff -ruN src/usr.sbin/pkg_install/lib/lib.h src/usr.sbin/pkg_install.new/lib/lib.h
--- src/usr.sbin/pkg_install/lib/lib.h	Tue Jan  4 17:18:55 2005
+++ src/usr.sbin/pkg_install.new/lib/lib.h	Fri Feb  4 00:07:09 2005
@@ -108,7 +108,8 @@
     PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE,
     PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY,
     PLIST_PKGDEP, PLIST_CONFLICTS, PLIST_MTREE, PLIST_DIR_RM, 
-    PLIST_IGNORE_INST, PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN
+    PLIST_DIR_RMIE, PLIST_RMIU, PLIST_CPIN, PLIST_IGNORE_INST,
+    PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN
 };
 typedef enum _plist_t plist_t;
 
@@ -170,6 +171,7 @@
 Boolean         isfile(const char *);
 Boolean		isempty(const char *);
 Boolean		issymlink(const char *);
+int		isdifferent(const char *, const char *);
 Boolean		isURL(const char *);
 char		*fileGetURL(const char *, const char *);
 char		*fileFindByPath(const char *, const char *);
diff -ruN src/usr.sbin/pkg_install/lib/plist.c src/usr.sbin/pkg_install.new/lib/plist.c
--- src/usr.sbin/pkg_install/lib/plist.c	Wed Jul 28 09:19:15 2004
+++ src/usr.sbin/pkg_install.new/lib/plist.c	Fri Feb  4 00:00:35 2005
@@ -247,6 +247,12 @@
 	return PLIST_MTREE;
     else if (!strcmp(cmd, "dirrm"))
 	return PLIST_DIR_RM;
+    else if (!strcmp(cmd, "dirrmie"))
+	return PLIST_DIR_RMIE;
+    else if (!strcmp(cmd, "rmiu"))
+	return PLIST_RMIU;
+    else if (!strcmp(cmd, "cpin"))
+	return PLIST_CPIN;
     else if (!strcmp(cmd, "option"))
 	return PLIST_OPTION;
     else
@@ -378,6 +384,18 @@
 	    fprintf(fp, "%cdirrm %s\n", CMD_CHAR, plist->name);
 	    break;
 
+	case PLIST_DIR_RMIE:
+	    fprintf(fp, "%cdirrmie %s\n", CMD_CHAR, plist->name);
+	    break;
+
+	case PLIST_RMIU:
+	    fprintf(fp, "%crmiu %s\n", CMD_CHAR, plist->name);
+	    break;
+
+	case PLIST_CPIN:
+	    fprintf(fp, "%ccpin %s\n", CMD_CHAR, plist->name);
+	    break;
+
 	case PLIST_OPTION:
 	    fprintf(fp, "%coption %s\n", CMD_CHAR, plist->name);
 	    break;
@@ -413,7 +431,7 @@
     const char *Where = ".", *last_file = "";
     Boolean fail = SUCCESS;
     Boolean preserve;
-    char tmp[FILENAME_MAX], *name = NULL;
+    char tmp[FILENAME_MAX], tmp2[FILENAME_MAX], *name = NULL;
 
     preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
     for (p = pkg->head; p; p = p->next) {
@@ -500,6 +518,7 @@
 	    break;
 
 	case PLIST_DIR_RM:
+	case PLIST_DIR_RMIE:
 	    sprintf(tmp, "%s/%s", Where, p->name);
 	    if (!isdir(tmp) && fexists(tmp)) {
 		warnx("cannot delete specified directory '%s' - it is a file!\n"
@@ -508,8 +527,26 @@
 	    else {
 		if (Verbose)
 		    printf("Delete directory %s\n", tmp);
-		if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) {
+		if (!Fake && delete_hierarchy(tmp, ign_err, FALSE) && p->type != PLIST_DIR_RMIE) {
 		    warnx("unable to completely remove directory '%s'", tmp);
+		    fail = FAIL;
+		}
+	    }
+	    last_file = p->name;
+	    break;
+
+	case PLIST_RMIU:
+	    sprintf(tmp, "%s/%s", Where, p->name);
+	    sprintf(tmp2, "%s/%s-dist", Where, p->name);
+	    if (!fexists(tmp) || !fexists(tmp2)) {
+		warnx("specified file '%s' or '%s' does not exist!\n"
+	"this packing list is incorrect - ignoring delete request", tmp, tmp2);
+	    }
+	    else if (!isdifferent(tmp, tmp2)) {
+		if (Verbose)
+		    printf("Delete file %s (unchanged)\n", tmp);
+		if (!Fake && vsystem("%s %s %s", REMOVE_CMD, (ign_err ? "-f" : ""), tmp)) {
+		    warnx("unable to remove file '%s'", tmp);
 		    fail = FAIL;
 		}
 	    }
--- pkg_install.diff ends here ---

--- dummy-1.0.shar begins here ---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	dummy
#	dummy/Makefile
#	dummy/pkg-descr
#	dummy/pkg-plist
#
echo c - dummy
mkdir -p dummy > /dev/null 2>&1
echo x - dummy/Makefile
sed 's/^X//' >dummy/Makefile << 'END-of-dummy/Makefile'
XPORTNAME=	dummy
XPORTVERSION=	1.0
XCATEGORIES=	misc
XDISTFILES=	
X
XMAINTAINER=	ports at FreeBSD.org
XCOMMENT=	Dummy port
X
XNO_BUILD=	yes
X
Xdo-install:
X	${MKDIR} ${DATADIR}
X	${INSTALL_DATA} ${.CURDIR}/Makefile ${DATADIR}/Makefile-dist
X	[ ! -f ${DATADIR}/Makefile ] && ${INSTALL_DATA} ${.CURDIR}/Makefile ${DATADIR}/Makefile
X
X.include <bsd.port.mk>
END-of-dummy/Makefile
echo x - dummy/pkg-descr
sed 's/^X//' >dummy/pkg-descr << 'END-of-dummy/pkg-descr'
XThis is a dummy port, for testing purposes.
X
XWWW: http://www.freebsd.org/
X
X- Florent Thoumie
Xflz at xbsd.org
END-of-dummy/pkg-descr
echo x - dummy/pkg-plist
sed 's/^X//' >dummy/pkg-plist << 'END-of-dummy/pkg-plist'
X at rmiu %%DATADIR%%/Makefile
X%%DATADIR%%/Makefile-dist
X at cpin %%DATADIR%%/Makefile
X at dirrmie %%DATADIR%%
END-of-dummy/pkg-plist
exit
--- dummy-1.0.shar ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list