changeset 10130:0c523179270e

5074117 installf problem with character and block special devices.
author phaniram rampura krishnamurthy - Sun Microsystems - Bangalore India <Phaniram.Krishnamurthy@Sun.COM>
date Mon, 20 Jul 2009 12:16:38 +0530
parents 089f053ced24
children 7fe254ca5fe8
files usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c usr/src/lib/libpkg/common/isdir.c usr/src/lib/libpkg/common/mapfile-vers usr/src/lib/libpkg/common/pkglib.h usr/src/lib/libpkg/common/verify.c
diffstat 5 files changed, 166 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c	Sun Jul 19 20:52:08 2009 -0700
+++ b/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c	Mon Jul 20 12:16:38 2009 +0530
@@ -99,7 +99,7 @@
 static int	do_like_ent(VFP_T *vfpo, struct cfextra *el_ent,
 		    struct cfent *cf_ent, int ctrl);
 static int	do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl);
-static int	typechg(struct cfent *el_ent, struct cfent *cf_ent,
+static int	typechg(struct cfent *el_ent, char *curftype,
 		    struct mergstat *mstat);
 
 static void	set_change(struct cfextra *el_ent);
@@ -549,6 +549,40 @@
 		 * about this later. Note that noconflict means NO conflict
 		 * at the file level. Even rogue files count.
 		 */
+		char myftype = '?';
+		int n = 0;
+
+		/* Get the existing file type on disk */
+		eval_ftype(el_ent->server_path, el_ent->cf_ent.ftype, &myftype);
+
+		/* Do the right thing if types are different */
+		n = typechg(&(el_ent->cf_ent), &myftype, &(el_ent->mstat));
+		switch (n) {
+			case TYPE_OK:
+					break;
+
+			/* This is an allowable change. */
+			case TYPE_WARNING:
+					el_ent->mstat.contchg = 1;
+					break;
+
+			/* Not allowed, but leaving it as is is OK. */
+			case TYPE_IGNORED:
+					break;
+
+			/* Future analysis will reveal if this is OK. */
+			case TYPE_REPLACE:
+					el_ent->mstat.replace = 1;
+					break;
+
+			/* Kill it before it does any damage. */
+			case TYPE_FATAL:
+					logerr(gettext(MSG_TYPE_ERR));
+					quit(99);
+
+			default:
+				break;
+		}
 		el_ent->mstat.shared = 1;
 		el_ent->mstat.rogue = 1;
 		set_change(el_ent);
@@ -725,20 +759,20 @@
  *	TYPE_FATAL	something awful happened
  */
 static int
-typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
+typechg(struct cfent *el_ent, char *curftype, struct mergstat *mstat)
 {
 	int	i, etype, itype, retcode;
 
 	/* If they are identical, return OK */
-	if (cf_ent->ftype == el_ent->ftype)
+	if (*curftype == el_ent->ftype)
 		return (TYPE_OK);
 
 	/*
 	 * If package database entry is ambiguous, set it to the new entity's
 	 * ftype
 	 */
-	if (cf_ent->ftype == BADFTYPE) {
-		cf_ent->ftype = el_ent->ftype;
+	if (*curftype == BADFTYPE) {
+		*curftype = el_ent->ftype;
 		return (TYPE_OK); /* do nothing; not really different */
 	}
 
@@ -751,7 +785,7 @@
 	 * exclusive directory, this is very dangerous. We will continue, but
 	 * we will deny the conversion.
 	 */
-	if (el_ent->ftype == 'x' && cf_ent->ftype == 'd') {
+	if (el_ent->ftype == 'x' && *curftype == 'd') {
 		logerr(gettext(WRN_TOEXCL), el_ent->path);
 		return (TYPE_IGNORED);
 	}
@@ -768,7 +802,7 @@
 
 	/* Set itype to that in the package database. */
 	for (i = 0; types[i]; ++i) {
-		if (strchr(types[i], cf_ent->ftype)) {
+		if (strchr(types[i], *curftype)) {
 			itype = i+1;
 			break;
 		}
@@ -792,36 +826,36 @@
 
 	/* allow change, but warn user of possible problems */
 	switch (itype) {
-	    case 1:
-		logerr(gettext(WRN_NOTFILE), el_ent->path);
-		break;
+		case 1:
+			logerr(gettext(WRN_NOTFILE), el_ent->path);
+			break;
 
-	    case 2:
-		logerr(gettext(WRN_NOTSYMLN), el_ent->path);
-		break;
+		case 2:
+			logerr(gettext(WRN_NOTSYMLN), el_ent->path);
+			break;
 
-	    case 3:
-		logerr(gettext(WRN_NOTLINK), el_ent->path);
-		break;
+		case 3:
+			logerr(gettext(WRN_NOTLINK), el_ent->path);
+			break;
 
-	    case 4:
-		logerr(gettext(WRN_NOTDIR), el_ent->path);
-		break;
+		case 4:
+			logerr(gettext(WRN_NOTDIR), el_ent->path);
+			break;
 
-	    case 5:
-		logerr(gettext(WRN_NOTCHAR), el_ent->path);
-		break;
+		case 5:
+			logerr(gettext(WRN_NOTCHAR), el_ent->path);
+			break;
 
-	    case 6:
-		logerr(gettext(WRN_NOTBLOCK), el_ent->path);
-		break;
+		case 6:
+			logerr(gettext(WRN_NOTBLOCK), el_ent->path);
+			break;
 
-	    case 7:
-		logerr(gettext(WRN_NOTPIPE), el_ent->path);
-		break;
+		case 7:
+			logerr(gettext(WRN_NOTPIPE), el_ent->path);
+			break;
 
-	    default:
-		break;
+		default:
+			break;
 	}
 	return (retcode);
 }
@@ -867,7 +901,8 @@
 	 * can't figure it 'til later (d -> s) or fatal (a hook for later).
 	 */
 	if (cf_ent->ftype != el_ent->cf_ent.ftype) {
-		n = typechg(&(el_ent->cf_ent), cf_ent, &(el_ent->mstat));
+		n = typechg(&(el_ent->cf_ent), &(cf_ent->ftype),
+		    &(el_ent->mstat));
 
 		switch (n) {
 		    case TYPE_OK:
--- a/usr/src/lib/libpkg/common/isdir.c	Sun Jul 19 20:52:08 2009 -0700
+++ b/usr/src/lib/libpkg/common/isdir.c	Mon Jul 20 12:16:38 2009 +0530
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,6 +40,7 @@
 #include <string.h>
 #include "pkglocale.h"
 #include "pkglibmsgs.h"
+#include "pkglib.h"
 
 /*
  * Defines for cpio/compression checks.
@@ -77,6 +78,7 @@
 int isdir(char *path);
 int isfile(char *dir, char *file);
 int iscpio(char *path, int *iscomp);
+int eval_ftype(char *path, char ftype, char *myftype);
 
 /*
  * Name:	isdir
@@ -389,3 +391,83 @@
 
 	(void) fclose(fp);
 }
+
+/*
+ * Name:	eval_ftype
+ * Description: Evaluate the target's file type
+ * Arguments:	path      - Path on filesystem
+ *		ftype     - Type to be changed to
+ *		myftype   - Address into which current
+ *			    type of target will be stored
+ * Returns:	int
+ *			0	 - Success
+ *			VE_EXIST - Path does not exist
+ *			VE_FTYPE - Path file type is not recognized,
+ *				   is not supported,
+ *				   or is not what is expected
+ */
+int
+eval_ftype(char *path, char ftype, char *myftype)
+{
+	struct stat status;
+	int retcode = 0;
+	int statError = 0;
+
+	/* If we are to process symlinks the old way then we follow the link */
+	if (nonABI_symlinks()) {
+		if ((ftype == 's') ? lstat(path, &status) :
+		    stat(path, &status)) {
+			(void) reperr(pkg_gt(ERR_EXIST));
+			retcode = VE_EXIST;
+			*myftype = '?';
+			statError++;
+		}
+	/* If not then we inspect the target of the link */
+	} else {
+		if (lstat(path, &status) == -1) {
+			reperr(pkg_gt(ERR_EXIST));
+			retcode = VE_EXIST;
+			*myftype = '?';
+			statError++;
+		}
+	}
+	if (!statError) {
+		/* determining actual type of existing object */
+		switch (status.st_mode & S_IFMT) {
+			case S_IFLNK:
+					*myftype = 's';
+					break;
+
+			case S_IFIFO:
+					*myftype = 'p';
+					break;
+
+			case S_IFCHR:
+					*myftype = 'c';
+					break;
+
+			case S_IFDIR:
+					*myftype = 'd';
+					break;
+
+			case S_IFBLK:
+					*myftype = 'b';
+					break;
+
+			case S_IFREG:
+			case 0:
+					*myftype = 'f';
+					break;
+
+			case S_IFDOOR:
+					*myftype = 'D';
+					break;
+
+			default:
+					*myftype = '?';
+					return (VE_FTYPE);
+		}
+		retcode = 0;
+	}
+	return (retcode);
+}
--- a/usr/src/lib/libpkg/common/mapfile-vers	Sun Jul 19 20:52:08 2009 -0700
+++ b/usr/src/lib/libpkg/common/mapfile-vers	Mon Jul 20 12:16:38 2009 +0530
@@ -89,6 +89,7 @@
 	epclose;
 	epopen;
 	esystem;
+	eval_ftype;
 	find_ca_certs;
 	find_cl_certs;
 	find_key_cert_pair;
--- a/usr/src/lib/libpkg/common/pkglib.h	Sun Jul 19 20:52:08 2009 -0700
+++ b/usr/src/lib/libpkg/common/pkglib.h	Mon Jul 20 12:16:38 2009 +0530
@@ -499,10 +499,12 @@
 extern void	ds_putinfo(char *buf);
 extern void	ds_skiptoend(char *device);
 extern void	ecleanup(void);
+extern int	eval_ftype(char *path, char ftype, char *myftype);
 /*PRINTFLIKE1*/
 extern void	logerr(char *fmt, ...);
 extern int	mappath(int flag, char *path);
 extern int	mapvar(int flag, char *varname);
+extern void	reperr(char *fmt, ...);
 /*PRINTFLIKE1*/
 extern void	progerr(char *fmt, ...);
 extern void	pkgerr(PKG_ERR *);
@@ -626,6 +628,7 @@
 extern int	isPathRemote();
 extern int	iscpio();
 extern int	isdir();
+extern int	eval_ftype();
 extern int	isfile();
 extern int	pkgexecl();
 extern int	pkgexecv();
@@ -653,6 +656,7 @@
 extern void	ds_skiptoend();
 extern void	ecleanup();
 extern void	logerr();
+extern void	reperr();
 extern int	mappath();
 extern int	mapvar();
 extern void	progerr();
--- a/usr/src/lib/libpkg/common/verify.c	Sun Jul 19 20:52:08 2009 -0700
+++ b/usr/src/lib/libpkg/common/verify.c	Mon Jul 20 12:16:38 2009 +0530
@@ -85,7 +85,7 @@
 } CHECKSUM_T;
 
 /*PRINTFLIKE1*/
-static void
+void
 reperr(char *fmt, ...)
 {
 	char	*pt;
@@ -392,7 +392,6 @@
 	int		uid, gid;
 	int		dochown;
 	int		retcode;
-	int		statError = 0;
 	int		targ_is_dir = 0;	/* replacing a directory */
 	char		myftype;
 	char		buf[PATH_MAX];
@@ -491,62 +490,19 @@
 
 	retcode = 0;
 
-	/* If we are to process symlinks the old way then we follow the link */
-	if (nonABI_symlinks()) {
-		if ((*ftype == 's') ? lstat(path, &status) :
-			stat(path, &status)) {
-			reperr(pkg_gt(ERR_EXIST));
-			retcode = VE_EXIST;
-			myftype = '?';
-			statError++;
-		}
-	/* If not then we inspect the target of the link */
-	} else {
-		if ((n = lstat(path, &status)) == -1) {
-			reperr(pkg_gt(ERR_EXIST));
-			retcode = VE_EXIST;
-			myftype = '?';
-			statError++;
-		}
-	}
-	if (!statError) {
-		/* determining actual type of existing object */
-		switch (status.st_mode & S_IFMT) {
-		    case S_IFLNK:
-			myftype = 's';
-			break;
+	/* Evaluate the file type of existing object */
+	retcode = eval_ftype(path, *ftype, &myftype);
 
-		    case S_IFIFO:
-			myftype = 'p';
-			break;
-
-		    case S_IFCHR:
-			myftype = 'c';
-			break;
-
-		    case S_IFDIR:
-			myftype = 'd';
-			targ_is_dir = 1;
-			break;
+	/*
+	 * If path file type is not recognized, is not supported or
+	 * is not what is expected, return
+	 */
+	if (retcode == VE_FTYPE)
+		return (retcode);
 
-		    case S_IFBLK:
-			myftype = 'b';
-			break;
-
-		    case S_IFREG:
-		    case 0:
-			myftype = 'f';
-			break;
-
-		    case S_IFDOOR:
-			myftype = 'D';
-			break;
-
-		    default:
-			reperr(pkg_gt(ERR_UNKNOWN));
-			return (VE_FTYPE);
-		}
-	}
+	/* If existing type is Directory, then set flag */
+	if (myftype == 'd')
+		targ_is_dir = 1;
 
 	if (setval) {
 		/*