#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <locale.h>
#include <libintl.h>
#include <errno.h>
#include "pkglib.h"
#include "install.h"
#include "libadm.h"
#include "libinst.h"
#include "pkginstall.h"
#include "messages.h"
extern char instdir[], pkgbin[], pkgloc[], savlog[], *pkginst, **environ;
extern char saveSpoolInstallDir[];
extern char pkgsav[];
static char *infoloc;
typedef unsigned int TBL_FLAG_T;
#define FLAG_NONE ((TBL_FLAG_T)0x0000)
#define FLAG_EXCLUDE ((TBL_FLAG_T)0x0001)
#define FLAG_IDENTICAL ((TBL_FLAG_T)0x0002)
#define TBL_ENTRY(_Y_, _F_) { (_Y_), ((sizeof ((_Y_)))-1), (_F_) }
struct _namelist {
char *_nlName;
int _nlLen;
TBL_FLAG_T _nlFlag;
};
typedef struct _namelist NAMELIST_T;
static NAMELIST_T attrTbl[] = {
TBL_ENTRY("BASEDIR=", FLAG_EXCLUDE),
TBL_ENTRY("CLASSES=", FLAG_EXCLUDE),
TBL_ENTRY("CLIENT_BASEDIR=", FLAG_EXCLUDE),
TBL_ENTRY("INST_DATADIR=", FLAG_EXCLUDE),
TBL_ENTRY("PKG_CAS_PASSRELATIVE=", FLAG_EXCLUDE),
TBL_ENTRY("PKG_DST_QKVERIFY=", FLAG_EXCLUDE),
TBL_ENTRY("PKG_INIT_INSTALL=", FLAG_EXCLUDE),
TBL_ENTRY("PKG_INSTALL_ROOT=", FLAG_EXCLUDE),
TBL_ENTRY("PKG_SRC_NOVERIFY=", FLAG_EXCLUDE),
TBL_ENTRY("SUNW_PKGCOND_GLOBAL_DATA=", FLAG_EXCLUDE),
TBL_ENTRY("SUNW_PKG_ALLZONES=", FLAG_IDENTICAL),
TBL_ENTRY("SUNW_PKG_DIR=", FLAG_EXCLUDE),
TBL_ENTRY("SUNW_PKG_HOLLOW=", FLAG_IDENTICAL),
TBL_ENTRY("SUNW_PKG_INSTALL_ZONENAME=", FLAG_EXCLUDE),
TBL_ENTRY("SUNW_PKG_THISZONE=", FLAG_IDENTICAL),
};
#define ATTRTBL_SIZE (sizeof (attrTbl) / sizeof (NAMELIST_T))
void
set_infoloc(char *path)
{
if (path && *path) {
if (is_an_inst_root()) {
infoloc = orig_path(path);
} else {
infoloc = strdup(path);
}
}
}
void
merginfo(struct cl_attr **pclass, int install_from_pspool)
{
DIR *pdirfp;
FILE *fp;
FILE *pkginfoFP;
char path[PATH_MAX];
char cmd[PATH_MAX];
char pkginfoPath[PATH_MAX];
char temp[PATH_MAX];
int i;
int nc;
int out;
(void) unlink(savlog);
if (is_spool_create() == 0) {
i = snprintf(pkginfoPath, sizeof (pkginfoPath),
"%s/var/sadm/pkg/%s/%s",
((get_inst_root()) &&
(strcmp(get_inst_root(), "/") != 0)) ?
get_inst_root() : "", pkginst,
PKGINFO);
if (i > sizeof (pkginfoPath)) {
progerr(ERR_CREATE_PATH_2,
((get_inst_root()) &&
(strcmp(get_inst_root(), "/") != 0)) ?
get_inst_root() : "/",
pkginst);
quit(1);
}
} else {
i = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/%s",
saveSpoolInstallDir, PKGINFO);
if (i > sizeof (pkginfoPath)) {
progerr(ERR_CREATE_PATH_2,
saveSpoolInstallDir, PKGINFO);
quit(1);
}
}
i = snprintf(path, PATH_MAX, "%s/%s", pkgloc, PKGINFO);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_2, pkgloc, PKGINFO);
quit(1);
}
echoDebug(DBG_MERGINFO_ENTRY,
instdir ? instdir : "??",
((get_inst_root()) &&
(strcmp(get_inst_root(), "/") != 0)) ?
get_inst_root() : "??",
saveSpoolInstallDir ? saveSpoolInstallDir : "??",
pkgloc ? pkgloc : "??", is_spool_create(),
get_info_basedir() ? get_info_basedir() : "??",
pkginfoPath, path);
if (strcmp(pkginfoPath, path) == 0) {
pkginfoFP = (FILE *)NULL;
echoDebug(DBG_MERGINFO_SAME, path);
} else {
echoDebug(DBG_MERGINFO_DIFFERENT, pkginfoPath, path);
pkginfoFP = fopen(pkginfoPath, "r");
if (pkginfoFP == (FILE *)NULL) {
echoDebug(ERR_NO_PKG_INFOFILE, pkginst, pkginfoPath,
strerror(errno));
}
}
if ((fp = fopen(path, "w")) == NULL) {
progerr(ERR_CANNOT_OPEN_FOR_WRITING, path, strerror(errno));
quit(99);
}
out = 0;
(void) fputs("CLASSES=", fp);
if (pclass) {
(void) fputs(pclass[0]->name, fp);
out++;
for (i = 1; pclass[i]; i++) {
(void) putc(' ', fp);
(void) fputs(pclass[i]->name, fp);
out++;
}
}
nc = cl_getn();
for (i = 0; i < nc; i++) {
int found = 0;
if (pclass) {
int j;
for (j = 0; pclass[j]; ++j) {
if (cl_nam(i) != NULL &&
strcmp(cl_nam(i),
pclass[j]->name) == 0) {
found++;
break;
}
}
}
if (!found) {
if (out > 0) {
(void) putc(' ', fp);
}
(void) fputs(cl_nam(i), fp);
out++;
}
}
(void) putc('\n', fp);
if (is_a_basedir()) {
static char *txs1 = "BASEDIR=";
(void) fputs(txs1, fp);
(void) fputs(get_info_basedir(), fp);
(void) putc('\n', fp);
} else {
(void) fputs("BASEDIR=/", fp);
(void) putc('\n', fp);
}
for (i = 0; environ[i] != (char *)NULL; i++) {
char *ep = environ[i];
int attrPos = -1;
int incr = (ATTRTBL_SIZE >> 1)+1;
int pos = ATTRTBL_SIZE >> 1;
NAMELIST_T *pp = (NAMELIST_T *)NULL;
if (strncmp(ep, attrTbl[0]._nlName, attrTbl[0]._nlLen) < 0) {
echoDebug(DBG_MERGINFO_LESS_THAN, ep,
attrTbl[0]._nlName);
} else if (strncmp(ep, attrTbl[ATTRTBL_SIZE-1]._nlName,
attrTbl[ATTRTBL_SIZE-1]._nlLen) > 0) {
echoDebug(DBG_MERGINFO_GREATER_THAN, ep,
attrTbl[ATTRTBL_SIZE-1]._nlName);
} else {
echoDebug(DBG_MERGINFO_SEARCHING, ep,
attrTbl[0]._nlName,
attrTbl[ATTRTBL_SIZE-1]._nlName);
while (incr > 0) {
int r;
pp = &attrTbl[pos];
r = strncmp(pp->_nlName, ep, pp->_nlLen);
if (r == 0) {
attrPos = pos;
break;
}
incr = incr >> 1;
pos += (r < 0) ? incr : -incr;
continue;
}
}
if ((attrPos >= 0) && (pp->_nlFlag == FLAG_EXCLUDE)) {
echoDebug(DBG_MERGINFO_EXCLUDING, ep);
continue;
}
if ((pkginfoFP != (FILE *)NULL) && (attrPos >= 0) &&
(pp->_nlFlag == FLAG_IDENTICAL)) {
char *src = ep+pp->_nlLen;
char *trg;
char theAttr[PATH_MAX+1];
(void) strncpy(theAttr, pp->_nlName, pp->_nlLen-1);
theAttr[pp->_nlLen-1] = '\0';
rewind(pkginfoFP);
trg = fpkgparam(pkginfoFP, theAttr);
echoDebug(DBG_MERGINFO_ATTRCOMP, theAttr,
trg ? trg : "");
if (trg == (char *)NULL) {
progerr(ERR_PKGINFO_ATTR_ADDED, pkginst, ep);
quit(1);
}
if (strcmp(src, trg) != 0) {
progerr(ERR_PKGINFO_ATTR_CHANGED, pkginst,
theAttr, src, trg);
quit(1);
}
}
if ((strncmp(ep, "PKGSAV=", 7) == 0)) {
(void) fputs("PKGSAV=", fp);
(void) fputs(infoloc, fp);
(void) putc('/', fp);
(void) fputs(pkginst, fp);
(void) fputs("/save\n", fp);
continue;
}
if ((strncmp(ep, "UPDATE=", 7) == 0) &&
install_from_pspool != 0 &&
!isUpdate()) {
continue;
}
echoDebug(DBG_MERGINFO_FINAL, ep);
(void) fputs(ep, fp);
(void) putc('\n', fp);
}
(void) fclose(fp);
(void) fclose(pkginfoFP);
i = snprintf(path, PATH_MAX, "%s/install", instdir);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_2, instdir, "/install");
quit(1);
}
if ((pdirfp = opendir(path)) != NULL) {
struct dirent *dp;
while ((dp = readdir(pdirfp)) != NULL) {
if (dp->d_name[0] == '.')
continue;
i = snprintf(path, PATH_MAX, "%s/install/%s",
instdir, dp->d_name);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_3, instdir, "/install/",
dp->d_name);
quit(1);
}
i = snprintf(temp, PATH_MAX, "%s/%s", pkgbin,
dp->d_name);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_2, pkgbin, dp->d_name);
quit(1);
}
if (cppath(MODE_SRC|DIR_DISPLAY, path, temp, 0644)) {
progerr(ERR_CANNOT_COPY, dp->d_name, pkgbin);
quit(99);
}
}
(void) closedir(pdirfp);
}
if (!is_spool_create()) {
i = snprintf(path, PATH_MAX, "%s/install", instdir);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_2, instdir, "/install");
quit(1);
}
if ((pdirfp = opendir(path)) != NULL) {
struct dirent *dp;
while ((dp = readdir(pdirfp)) != NULL) {
if (dp->d_name[0] == '.')
continue;
if (strcmp(dp->d_name, "i.none") == 0)
continue;
i = snprintf(path, PATH_MAX, "%s/install/%s",
instdir, dp->d_name);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_3, instdir,
"/install/", dp->d_name);
quit(1);
}
i = snprintf(temp, PATH_MAX, "%s/install/%s",
saveSpoolInstallDir,
dp->d_name);
if (i > PATH_MAX) {
progerr(ERR_CREATE_PATH_3,
saveSpoolInstallDir,
"/install/", dp->d_name);
quit(1);
}
if (cppath(MODE_SRC, path, temp, 0644)) {
progerr(ERR_CANNOT_COPY, path, temp);
(void) closedir(pdirfp);
quit(99);
}
}
(void) closedir(pdirfp);
}
i = snprintf(path, sizeof (path), "%s/%s", instdir, PKGINFO);
if (i > sizeof (path)) {
progerr(ERR_CREATE_PATH_2, instdir, PKGINFO);
quit(1);
}
i = snprintf(temp, sizeof (temp), "%s/%s",
saveSpoolInstallDir, PKGINFO);
if (i > sizeof (temp)) {
progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
PKGINFO);
quit(1);
}
if (cppath(MODE_SRC, path, temp, 0644)) {
progerr(ERR_CANNOT_COPY, path, temp);
quit(99);
}
i = snprintf(path, sizeof (path), "%s/pkgmap", instdir);
if (i > sizeof (path)) {
progerr(ERR_CREATE_PATH_2, instdir, "pkgmap");
quit(1);
}
i = snprintf(temp, sizeof (temp), "%s/pkgmap",
saveSpoolInstallDir);
if (i > sizeof (path)) {
progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
"pkgmap");
quit(1);
}
if (cppath(MODE_SRC, path, temp, 0644)) {
progerr(ERR_CANNOT_COPY, path, temp);
quit(99);
}
}
if (strstr(instdir, "pspool") != NULL) {
struct stat status;
i = snprintf(path, sizeof (path), "%s/save", instdir);
if (i > sizeof (path)) {
progerr(ERR_CREATE_PATH_2, instdir, "save");
quit(1);
}
if ((stat(path, &status) == 0) && (status.st_mode & S_IFDIR)) {
i = snprintf(cmd, sizeof (cmd), "cp -pr %s/* %s",
path, pkgsav);
if (i > sizeof (cmd)) {
progerr(ERR_SNPRINTF, "cp -pr %s/* %s");
quit(1);
}
if (system(cmd)) {
progerr(ERR_PKGBINCP, path, pkgsav);
quit(99);
}
}
}
}