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