summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphaniram rampura krishnamurthy - Sun Microsystems - Bangalore India <Phaniram.Krishnamurthy@Sun.COM>2009-07-20 12:16:38 +0530
committerphaniram rampura krishnamurthy - Sun Microsystems - Bangalore India <Phaniram.Krishnamurthy@Sun.COM>2009-07-20 12:16:38 +0530
commit0ba964ea1a9461d43c8e39e5a9a3ab857e6786c7 (patch)
tree31e5b1c8fd740de608505c54394c04aaf24d69b1
parentce0bfb39c0479ba97372eb0e5bf2ef4275d0876e (diff)
downloadillumos-joyent-0ba964ea1a9461d43c8e39e5a9a3ab857e6786c7.tar.gz
5074117 installf problem with character and block special devices.
-rw-r--r--usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c97
-rw-r--r--usr/src/lib/libpkg/common/isdir.c84
-rw-r--r--usr/src/lib/libpkg/common/mapfile-vers1
-rw-r--r--usr/src/lib/libpkg/common/pkglib.h4
-rw-r--r--usr/src/lib/libpkg/common/verify.c72
5 files changed, 168 insertions, 90 deletions
diff --git a/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c b/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c
index 4c0af8810d..5f9795d147 100644
--- a/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c
+++ b/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c
@@ -99,7 +99,7 @@ static int merg(struct cfextra *el_ent, struct cfent *cf_ent);
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 @@ do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl)
* 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 @@ char *types[] = {
* 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 @@ typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
* 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 @@ typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
/* 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 @@ typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
/* 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 @@ merg(struct cfextra *el_ent, struct cfent *cf_ent)
* 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:
diff --git a/usr/src/lib/libpkg/common/isdir.c b/usr/src/lib/libpkg/common/isdir.c
index 55b59d5e67..9ae2751fc6 100644
--- a/usr/src/lib/libpkg/common/isdir.c
+++ b/usr/src/lib/libpkg/common/isdir.c
@@ -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 isFstypeRemote(char *a_fstype);
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 @@ _InitRemoteFstypes(void)
(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);
+}
diff --git a/usr/src/lib/libpkg/common/mapfile-vers b/usr/src/lib/libpkg/common/mapfile-vers
index f1fd2a8001..81934e31ae 100644
--- a/usr/src/lib/libpkg/common/mapfile-vers
+++ b/usr/src/lib/libpkg/common/mapfile-vers
@@ -89,6 +89,7 @@ SUNWprivate {
epclose;
epopen;
esystem;
+ eval_ftype;
find_ca_certs;
find_cl_certs;
find_key_cert_pair;
diff --git a/usr/src/lib/libpkg/common/pkglib.h b/usr/src/lib/libpkg/common/pkglib.h
index 04b17730ca..feb80d1d0f 100644
--- a/usr/src/lib/libpkg/common/pkglib.h
+++ b/usr/src/lib/libpkg/common/pkglib.h
@@ -499,10 +499,12 @@ extern void ds_order(char *list[]);
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 isFstypeRemote();
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_putinfo();
extern void ds_skiptoend();
extern void ecleanup();
extern void logerr();
+extern void reperr();
extern int mappath();
extern int mapvar();
extern void progerr();
diff --git a/usr/src/lib/libpkg/common/verify.c b/usr/src/lib/libpkg/common/verify.c
index c48c5b8c77..1af2d2778c 100644
--- a/usr/src/lib/libpkg/common/verify.c
+++ b/usr/src/lib/libpkg/common/verify.c
@@ -85,7 +85,7 @@ typedef union hilo {
} CHECKSUM_T;
/*PRINTFLIKE1*/
-static void
+void
reperr(char *fmt, ...)
{
char *pt;
@@ -392,7 +392,6 @@ averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
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 @@ averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
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;
-
- case S_IFIFO:
- myftype = 'p';
- break;
-
- case S_IFCHR:
- myftype = 'c';
- break;
-
- case S_IFDIR:
- myftype = 'd';
- targ_is_dir = 1;
- break;
-
- 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);
- }
- }
+ /* Evaluate the file type of existing object */
+ retcode = eval_ftype(path, *ftype, &myftype);
+
+ /*
+ * If path file type is not recognized, is not supported or
+ * is not what is expected, return
+ */
+ if (retcode == VE_FTYPE)
+ return (retcode);
+
+ /* If existing type is Directory, then set flag */
+ if (myftype == 'd')
+ targ_is_dir = 1;
if (setval) {
/*