#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <pkgstrct.h>
#include <locale.h>
#include <libintl.h>
#include <pkglib.h>
#include <install.h>
#include <libinst.h>
#define ERR_MEMORY "memory allocation failure"
#define ERR_DUPPATH "duplicate pathname <%s>"
extern int getmapmode(void);
#define EPTMALLOC 512
static struct cfent **eptlist;
static int eptnum;
static int errflg;
static int nparts;
static int space = -1;
static void procinit(void);
static int procassign(struct cfent *ept, char **server_local,
char **client_local, char **server_path,
char **client_path, char **map_path, int mapflag,
int nc);
static int ckdup(struct cfent *ept1, struct cfent *ept2);
static int sortentry(int index);
static void
procinit(void)
{
errflg = nparts = eptnum = 0;
if (space != -1) {
ar_free(space);
space = -1;
}
(void) pathdup((char *)0);
}
static int
procassign(struct cfent *ept, char **server_local, char **client_local,
char **server_path, char **client_path, char **map_path, int mapflag,
int nc)
{
int path_duped = 0;
int local_duped = 0;
char source[PATH_MAX+1];
if (nc >= 0 && ept->ftype != 'i')
if ((ept->pkg_class_idx = cl_idx(ept->pkg_class)) == -1)
return (1);
if (ept->volno > nparts)
nparts++;
if ((mapflag > 1) && strchr("fve", ept->ftype)) {
if (ept->ainfo.local == NULL) {
source[0] = '~';
(void) strcpy(&source[1], ept->path);
ept->ainfo.local = pathdup(source);
*server_local = ept->ainfo.local;
*client_local = ept->ainfo.local;
local_duped = 1;
}
}
if (mapflag && (ept->ftype != 'i')) {
mappath(getmapmode(), ept->path);
canonize(ept->path);
(void) eval_path(server_path,
client_path,
map_path,
ept->path);
path_duped = 1;
ept->path = *server_path;
}
if (strchr("sl", ept->ftype)) {
if (mapflag) {
mappath(getmapmode(), ept->ainfo.local);
if (!RELATIVE(ept->ainfo.local)) {
canonize(ept->ainfo.local);
if (ept->ftype == 'l') {
(void) eval_path(
server_local,
client_local,
NULL,
ept->ainfo.local);
local_duped = 1;
ept->ainfo.local = *server_local;
}
}
}
}
if (!path_duped) {
*server_path = pathdup(ept->path);
*client_path = *server_path;
ept->path = *server_path;
path_duped = 1;
}
if (ept->ainfo.local != NULL)
if (!local_duped) {
*server_local = pathdup(ept->ainfo.local);
ept->ainfo.local = *server_local;
*client_local = ept->ainfo.local;
local_duped = 1;
}
return (0);
}
struct cfent **
procmap(VFP_T *vfp, int mapflag, char *ir)
{
struct cfent *ept = (struct cfent *)NULL;
struct cfent map_entry;
struct cfent **ept_ptr;
int i;
int n;
int nc;
static char *server_local, *client_local;
static char *server_path, *client_path, *map_path;
procinit();
space = ar_create(EPTMALLOC, (unsigned)sizeof (struct cfent),
"prototype object");
if (space == -1) {
progerr(gettext(ERR_MEMORY));
return (NULL);
}
nc = cl_getn();
for (;;) {
(void) memset(&map_entry, '\000', sizeof (struct cfent));
n = gpkgmapvfp(&map_entry, vfp);
if (n == 0)
break;
else if (n < 0) {
char *errstr = getErrstr();
progerr(gettext("bad entry read in pkgmap"));
logerr(gettext("pathname=%s"),
(ept && ept->path && *ept->path) ?
ept->path : "Unknown");
logerr(gettext("problem=%s"),
(errstr && *errstr) ? errstr : "Unknown");
return (NULL);
}
ept_ptr = (struct cfent **)ar_next_avail(space);
if (ept_ptr == NULL || *ept_ptr == NULL) {
progerr(gettext(ERR_MEMORY));
return (NULL);
}
ept = *ept_ptr;
(void) memcpy(ept, &map_entry, sizeof (struct cfent));
if (procassign(ept, &server_local, &client_local,
&server_path, &client_path, &map_path,
mapflag, nc)) {
(void) ar_delete(space, eptnum);
continue;
}
eptnum++;
}
eptlist = (struct cfent **)ar_get_head(space);
if (eptlist == NULL) {
progerr(gettext(ERR_MEMORY));
return (NULL);
}
(void) sortentry(-1);
for (i = 0; i < eptnum; ) {
if (!sortentry(i))
i++;
}
return (errflg ? NULL : eptlist);
}
static int
sortentry(int index)
{
struct cfent *ept, *ept_i;
static int last = 0;
int i, n, j;
int upper, lower;
if (index == 0)
return (0);
else if (index < 0) {
last = 0;
return (0);
}
ept = eptlist[index];
if (strcmp(ept->path, eptlist[index-1]->path) > 0) {
last = index-1;
return (0);
}
lower = 0;
upper = index;
i = last;
do {
ept_i = eptlist[i];
n = strcmp(ept->path, ept_i->path);
if (n == 0) {
if (!ckdup(ept, ept_i)) {
progerr(gettext(ERR_DUPPATH),
ept->path);
errflg++;
}
(void) ar_delete(space, index);
eptnum--;
return (1);
} else if (n < 0) {
upper = i;
i = lower + (upper-lower)/2;
} else {
lower = i+1;
i = upper - (upper-lower)/2 - 1;
}
} while (upper != lower);
last = i = upper;
for (j = index; j > i; j--)
eptlist[j] = eptlist[j-1];
eptlist[i] = ept;
return (0);
}
static int
ckdup(struct cfent *ept1, struct cfent *ept2)
{
if (!strchr("?dx", ept1->ftype))
return (0);
if (!strchr("?dx", ept2->ftype))
return (0);
if (ept2->ainfo.mode == BADMODE)
ept2->ainfo.mode = ept1->ainfo.mode;
if ((ept1->ainfo.mode != ept2->ainfo.mode) &&
(ept1->ainfo.mode != BADMODE))
return (0);
if (strcmp(ept2->ainfo.owner, "?") == 0)
(void) strcpy(ept2->ainfo.owner, ept1->ainfo.owner);
if (strcmp(ept1->ainfo.owner, ept2->ainfo.owner) &&
strcmp(ept1->ainfo.owner, "?"))
return (0);
if (strcmp(ept2->ainfo.group, "?") == 0)
(void) strcpy(ept2->ainfo.group, ept1->ainfo.group);
if (strcmp(ept1->ainfo.group, ept2->ainfo.group) &&
strcmp(ept1->ainfo.group, "?"))
return (0);
if (ept1->pinfo) {
ept2->npkgs = ept1->npkgs;
ept2->pinfo = ept1->pinfo;
}
return (1);
}