15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland * CDDL HEADER START
35c51f124SMoriah Waterland *
45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland *
85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland * See the License for the specific language governing permissions
115c51f124SMoriah Waterland * and limitations under the License.
125c51f124SMoriah Waterland *
135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland *
195c51f124SMoriah Waterland * CDDL HEADER END
205c51f124SMoriah Waterland */
215c51f124SMoriah Waterland
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
245c51f124SMoriah Waterland * Use is subject to license terms.
255c51f124SMoriah Waterland */
265c51f124SMoriah Waterland
275c51f124SMoriah Waterland
285c51f124SMoriah Waterland #include <stdio.h>
295c51f124SMoriah Waterland #include <limits.h>
305c51f124SMoriah Waterland #include <stdlib.h>
315c51f124SMoriah Waterland #include <unistd.h>
325c51f124SMoriah Waterland #include <errno.h>
335c51f124SMoriah Waterland #include <string.h>
345c51f124SMoriah Waterland #include <sys/types.h>
355c51f124SMoriah Waterland #include <pkgstrct.h>
365c51f124SMoriah Waterland #include <locale.h>
375c51f124SMoriah Waterland #include <libintl.h>
385c51f124SMoriah Waterland #include <pkglib.h>
395c51f124SMoriah Waterland #include <install.h>
405c51f124SMoriah Waterland #include <libinst.h>
415c51f124SMoriah Waterland
425c51f124SMoriah Waterland #define WRN_NOPKGOBJ "WARNING: no package objects found"
435c51f124SMoriah Waterland
445c51f124SMoriah Waterland #define ERR_MEMORY "memory allocation failure"
455c51f124SMoriah Waterland #define ERR_DUPPATH "duplicate pathname <%s>"
465c51f124SMoriah Waterland
475c51f124SMoriah Waterland /* libpkg/gpkgmap */
485c51f124SMoriah Waterland extern int getmapmode(void);
495c51f124SMoriah Waterland
505c51f124SMoriah Waterland #define EPTMALLOC 512
515c51f124SMoriah Waterland
525c51f124SMoriah Waterland static struct cfextra **extlist;
535c51f124SMoriah Waterland
545c51f124SMoriah Waterland int eptnum;
555c51f124SMoriah Waterland static int array_preloaded = 0;
565c51f124SMoriah Waterland static int errflg;
575c51f124SMoriah Waterland static int nparts;
585c51f124SMoriah Waterland static int xspace = -1;
595c51f124SMoriah Waterland
605c51f124SMoriah Waterland void pkgobjinit(void);
615c51f124SMoriah Waterland static int pkgobjassign(struct cfent *ept, char **server_local,
625c51f124SMoriah Waterland char **client_local, char **server_path,
635c51f124SMoriah Waterland char **client_path, char **map_path, int mapflag,
645c51f124SMoriah Waterland int nc);
655c51f124SMoriah Waterland
665c51f124SMoriah Waterland static int ckdup(struct cfent *ept1, struct cfent *ept2);
675c51f124SMoriah Waterland static int sortentry(int index);
685c51f124SMoriah Waterland static int dup_merg(struct cfextra *ext1, struct cfextra *ext2);
695c51f124SMoriah Waterland
705c51f124SMoriah Waterland void
pkgobjinit(void)715c51f124SMoriah Waterland pkgobjinit(void)
725c51f124SMoriah Waterland {
735c51f124SMoriah Waterland if (array_preloaded) /* Already done. */
745c51f124SMoriah Waterland return;
755c51f124SMoriah Waterland
765c51f124SMoriah Waterland errflg = nparts = eptnum = 0;
775c51f124SMoriah Waterland
785c51f124SMoriah Waterland if (xspace != -1) {
795c51f124SMoriah Waterland ar_free(xspace);
805c51f124SMoriah Waterland xspace = -1;
815c51f124SMoriah Waterland }
825c51f124SMoriah Waterland
835c51f124SMoriah Waterland /*
845c51f124SMoriah Waterland * initialize dynamic memory used to store
855c51f124SMoriah Waterland * path information which is read in
865c51f124SMoriah Waterland */
875c51f124SMoriah Waterland (void) pathdup((char *)0);
885c51f124SMoriah Waterland }
895c51f124SMoriah Waterland
905c51f124SMoriah Waterland /*
915c51f124SMoriah Waterland * This function assigns appropriate values based upon the pkgmap entry
925c51f124SMoriah Waterland * in the cfent structure.
935c51f124SMoriah Waterland */
945c51f124SMoriah Waterland static int
pkgobjassign(struct cfent * ept,char ** server_local,char ** client_local,char ** server_path,char ** client_path,char ** map_path,int mapflag,int nc)955c51f124SMoriah Waterland pkgobjassign(struct cfent *ept, char **server_local, char **client_local,
965c51f124SMoriah Waterland char **server_path, char **client_path, char **map_path, int mapflag,
975c51f124SMoriah Waterland int nc)
985c51f124SMoriah Waterland {
995c51f124SMoriah Waterland int path_duped = 0;
1005c51f124SMoriah Waterland int local_duped = 0;
1015c51f124SMoriah Waterland char source[PATH_MAX+1];
1025c51f124SMoriah Waterland
1035c51f124SMoriah Waterland if (nc >= 0 && ept->ftype != 'i')
1045c51f124SMoriah Waterland if ((ept->pkg_class_idx = cl_idx(ept->pkg_class)) == -1)
1055c51f124SMoriah Waterland return (1);
1065c51f124SMoriah Waterland
1075c51f124SMoriah Waterland if (ept->volno > nparts)
1085c51f124SMoriah Waterland nparts++;
1095c51f124SMoriah Waterland
1105c51f124SMoriah Waterland /*
1115c51f124SMoriah Waterland * Generate local (delivered source) paths for files
1125c51f124SMoriah Waterland * which need them so that the install routine will know
1135c51f124SMoriah Waterland * where to get the file from the package. Note that we
1145c51f124SMoriah Waterland * do not resolve path environment variables here since
1155c51f124SMoriah Waterland * they won't be resolved in the reloc directory.
1165c51f124SMoriah Waterland */
1175c51f124SMoriah Waterland if ((mapflag > 1) && strchr("fve", ept->ftype)) {
1185c51f124SMoriah Waterland if (ept->ainfo.local == NULL) {
1195c51f124SMoriah Waterland source[0] = '~';
1205c51f124SMoriah Waterland (void) strlcpy(&source[1], ept->path,
1215c51f124SMoriah Waterland sizeof (source)-1);
1225c51f124SMoriah Waterland ept->ainfo.local = pathdup(source);
1235c51f124SMoriah Waterland *server_local = ept->ainfo.local;
1245c51f124SMoriah Waterland *client_local = ept->ainfo.local;
1255c51f124SMoriah Waterland
1265c51f124SMoriah Waterland local_duped = 1;
1275c51f124SMoriah Waterland }
1285c51f124SMoriah Waterland }
1295c51f124SMoriah Waterland
1305c51f124SMoriah Waterland /*
1315c51f124SMoriah Waterland * Evaluate the destination path based upon available
1325c51f124SMoriah Waterland * environment, then produce a client-relative and
1335c51f124SMoriah Waterland * server-relative canonized path.
1345c51f124SMoriah Waterland */
1355c51f124SMoriah Waterland if (mapflag && (ept->ftype != 'i')) {
1365c51f124SMoriah Waterland mappath(getmapmode(), ept->path); /* evaluate variables */
1375c51f124SMoriah Waterland canonize(ept->path); /* Fix path as necessary. */
1385c51f124SMoriah Waterland
1395c51f124SMoriah Waterland (void) eval_path(server_path,
1405c51f124SMoriah Waterland client_path,
1415c51f124SMoriah Waterland map_path,
1425c51f124SMoriah Waterland ept->path);
1435c51f124SMoriah Waterland path_duped = 1; /* eval_path dup's it */
1445c51f124SMoriah Waterland ept->path = *server_path; /* default */
1455c51f124SMoriah Waterland }
1465c51f124SMoriah Waterland
1475c51f124SMoriah Waterland /*
1485c51f124SMoriah Waterland * Deal with source for hard and soft links.
1495c51f124SMoriah Waterland */
1505c51f124SMoriah Waterland if (strchr("sl", ept->ftype)) {
1515c51f124SMoriah Waterland if (mapflag) {
1525c51f124SMoriah Waterland mappath(getmapmode(), ept->ainfo.local);
1535c51f124SMoriah Waterland if (!RELATIVE(ept->ainfo.local)) {
1545c51f124SMoriah Waterland canonize(ept->ainfo.local);
1555c51f124SMoriah Waterland
1565c51f124SMoriah Waterland /* check for hard link */
1575c51f124SMoriah Waterland if (ept->ftype == 'l') {
1585c51f124SMoriah Waterland (void) eval_path(
1595c51f124SMoriah Waterland server_local,
1605c51f124SMoriah Waterland client_local,
1615c51f124SMoriah Waterland NULL,
1625c51f124SMoriah Waterland ept->ainfo.local);
1635c51f124SMoriah Waterland local_duped = 1;
1645c51f124SMoriah Waterland
1655c51f124SMoriah Waterland /* Default to server. */
1665c51f124SMoriah Waterland ept->ainfo.local = *server_local;
1675c51f124SMoriah Waterland }
1685c51f124SMoriah Waterland }
1695c51f124SMoriah Waterland }
1705c51f124SMoriah Waterland }
1715c51f124SMoriah Waterland
1725c51f124SMoriah Waterland /*
1735c51f124SMoriah Waterland * For the paths (both source and target) that were too mundane to
1745c51f124SMoriah Waterland * have been copied into dup space yet, do that.
1755c51f124SMoriah Waterland */
1765c51f124SMoriah Waterland if (!path_duped) {
1775c51f124SMoriah Waterland *server_path = pathdup(ept->path);
1785c51f124SMoriah Waterland *client_path = *server_path;
1795c51f124SMoriah Waterland ept->path = *server_path;
1805c51f124SMoriah Waterland
1815c51f124SMoriah Waterland path_duped = 1;
1825c51f124SMoriah Waterland }
1835c51f124SMoriah Waterland if (ept->ainfo.local != NULL)
1845c51f124SMoriah Waterland if (!local_duped) {
1855c51f124SMoriah Waterland *server_local = pathdup(ept->ainfo.local);
1865c51f124SMoriah Waterland ept->ainfo.local = *server_local;
1875c51f124SMoriah Waterland *client_local = ept->ainfo.local;
1885c51f124SMoriah Waterland
1895c51f124SMoriah Waterland local_duped = 1;
1905c51f124SMoriah Waterland }
1915c51f124SMoriah Waterland
1925c51f124SMoriah Waterland return (0);
1935c51f124SMoriah Waterland }
1945c51f124SMoriah Waterland
1955c51f124SMoriah Waterland /* This initializes the package object array. */
1965c51f124SMoriah Waterland int
init_pkgobjspace(void)1975c51f124SMoriah Waterland init_pkgobjspace(void)
1985c51f124SMoriah Waterland {
1995c51f124SMoriah Waterland if (array_preloaded) /* Already done. */
2005c51f124SMoriah Waterland return (1);
2015c51f124SMoriah Waterland
2025c51f124SMoriah Waterland if (xspace == -1) {
2035c51f124SMoriah Waterland xspace = ar_create(EPTMALLOC, sizeof (struct cfextra),
2045c51f124SMoriah Waterland "package object");
2055c51f124SMoriah Waterland if (xspace == -1) {
2065c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY));
2075c51f124SMoriah Waterland return (0);
2085c51f124SMoriah Waterland }
2095c51f124SMoriah Waterland }
2105c51f124SMoriah Waterland
2115c51f124SMoriah Waterland return (1);
2125c51f124SMoriah Waterland }
2135c51f124SMoriah Waterland
2145c51f124SMoriah Waterland int
seed_pkgobjmap(struct cfextra * ext_entry,char * path,char * local)2155c51f124SMoriah Waterland seed_pkgobjmap(struct cfextra *ext_entry, char *path, char *local)
2165c51f124SMoriah Waterland {
2175c51f124SMoriah Waterland struct cfextra *ext, **ext_ptr;
2185c51f124SMoriah Waterland
2195c51f124SMoriah Waterland /* offsets for the various path images. */
2205c51f124SMoriah Waterland int client_path_os;
2215c51f124SMoriah Waterland int server_path_os;
2225c51f124SMoriah Waterland int map_path_os;
2235c51f124SMoriah Waterland int client_local_os;
2245c51f124SMoriah Waterland int server_local_os;
2255c51f124SMoriah Waterland
2265c51f124SMoriah Waterland ext_ptr = (struct cfextra **)ar_next_avail(xspace);
2275c51f124SMoriah Waterland
2285c51f124SMoriah Waterland if (ext_ptr == NULL || *ext_ptr == NULL) {
2295c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY));
230*c57b7750SToomas Soome return (0);
2315c51f124SMoriah Waterland }
2325c51f124SMoriah Waterland
2335c51f124SMoriah Waterland ext = *ext_ptr;
2345c51f124SMoriah Waterland
2355c51f124SMoriah Waterland (void) memcpy(ext, ext_entry, sizeof (struct cfextra));
2365c51f124SMoriah Waterland
2375c51f124SMoriah Waterland /* Figure out all of the offsets. */
2385c51f124SMoriah Waterland client_path_os = ((ptrdiff_t)ext->client_path -
2395c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path);
2405c51f124SMoriah Waterland server_path_os = ((ptrdiff_t)ext->server_path -
2415c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path);
2425c51f124SMoriah Waterland map_path_os = ((ptrdiff_t)ext->map_path -
2435c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path);
2445c51f124SMoriah Waterland client_local_os = ((ptrdiff_t)ext->client_local -
2455c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.ainfo.local);
2465c51f124SMoriah Waterland server_local_os = ((ptrdiff_t)ext->server_local -
2475c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.ainfo.local);
2485c51f124SMoriah Waterland
2495c51f124SMoriah Waterland /* Allocate and store the path name. */
2505c51f124SMoriah Waterland ext->cf_ent.path = pathdup(path);
2515c51f124SMoriah Waterland
2525c51f124SMoriah Waterland /* Assign the path substring pointers. */
2535c51f124SMoriah Waterland ext->client_path = (ext->cf_ent.path + client_path_os);
2545c51f124SMoriah Waterland ext->server_path = (ext->cf_ent.path + server_path_os);
2555c51f124SMoriah Waterland ext->map_path = (ext->cf_ent.path + map_path_os);
2565c51f124SMoriah Waterland
2575c51f124SMoriah Waterland /* If there's a local entry, allocate and store it as well. */
2585c51f124SMoriah Waterland if (local) {
2595c51f124SMoriah Waterland ext->cf_ent.ainfo.local = pathdup(local);
2605c51f124SMoriah Waterland
2615c51f124SMoriah Waterland ext->client_local = (ext->cf_ent.ainfo.local + client_local_os);
2625c51f124SMoriah Waterland ext->server_local = (ext->cf_ent.ainfo.local + server_local_os);
2635c51f124SMoriah Waterland } else {
2645c51f124SMoriah Waterland ext->cf_ent.ainfo.local = NULL;
2655c51f124SMoriah Waterland ext->client_local = NULL;
2665c51f124SMoriah Waterland ext->server_local = NULL;
2675c51f124SMoriah Waterland }
2685c51f124SMoriah Waterland
2695c51f124SMoriah Waterland eptnum++;
2705c51f124SMoriah Waterland array_preloaded = 1;
2715c51f124SMoriah Waterland
2725c51f124SMoriah Waterland return (0);
2735c51f124SMoriah Waterland }
2745c51f124SMoriah Waterland
2755c51f124SMoriah Waterland /*
2765c51f124SMoriah Waterland * This function reads the pkgmap (or any file similarly formatted) and
2775c51f124SMoriah Waterland * returns a pointer to a list of struct cfextra (each of which
2785c51f124SMoriah Waterland * contains a struct cfent) representing the contents of that file.
2795c51f124SMoriah Waterland */
2805c51f124SMoriah Waterland
2815c51f124SMoriah Waterland /* ARGSUSED ir in pkgobjmap */
2825c51f124SMoriah Waterland struct cfextra **
pkgobjmap(VFP_T * vfp,int mapflag,char * ir)2835c51f124SMoriah Waterland pkgobjmap(VFP_T *vfp, int mapflag, char *ir)
2845c51f124SMoriah Waterland {
2855c51f124SMoriah Waterland struct cfextra *ext, **ext_ptr;
2865c51f124SMoriah Waterland struct cfent *ept, map_entry;
2875c51f124SMoriah Waterland int i;
2885c51f124SMoriah Waterland int n;
2895c51f124SMoriah Waterland int nc;
2905c51f124SMoriah Waterland
2915c51f124SMoriah Waterland pkgobjinit();
2925c51f124SMoriah Waterland if (!init_pkgobjspace())
2935c51f124SMoriah Waterland quit(99);
2945c51f124SMoriah Waterland
2955c51f124SMoriah Waterland nc = cl_getn();
2965c51f124SMoriah Waterland for (;;) {
2975c51f124SMoriah Waterland /* Clear the buffer. */
2985c51f124SMoriah Waterland (void) memset(&map_entry, '\000', sizeof (struct cfent));
2995c51f124SMoriah Waterland
3005c51f124SMoriah Waterland /*
3015c51f124SMoriah Waterland * Fill in a cfent structure in a very preliminary fashion.
3025c51f124SMoriah Waterland * ept->path and ept->ainfo.local point to static memory
3035c51f124SMoriah Waterland * areas of size PATH_MAX. These are manipulated and
3045c51f124SMoriah Waterland * then provided their own allocations later in this function.
3055c51f124SMoriah Waterland */
3065c51f124SMoriah Waterland n = gpkgmapvfp(&map_entry, vfp);
3075c51f124SMoriah Waterland
3085c51f124SMoriah Waterland if (n == 0)
3095c51f124SMoriah Waterland break; /* no more entries in pkgmap */
3105c51f124SMoriah Waterland else if (n < 0) {
3115c51f124SMoriah Waterland char *errstr = getErrstr();
3125c51f124SMoriah Waterland progerr(gettext("bad entry read in pkgmap"));
3135c51f124SMoriah Waterland logerr(gettext("pathname=%s"),
3145c51f124SMoriah Waterland (map_entry.path && *map_entry.path) ?
3155c51f124SMoriah Waterland map_entry.path : "Unknown");
3165c51f124SMoriah Waterland logerr(gettext("problem=%s"),
3175c51f124SMoriah Waterland (errstr && *errstr) ? errstr : "Unknown");
3185c51f124SMoriah Waterland return (NULL);
3195c51f124SMoriah Waterland }
3205c51f124SMoriah Waterland
3215c51f124SMoriah Waterland /*
3225c51f124SMoriah Waterland * A valid entry was found in the map, so allocate an
3235c51f124SMoriah Waterland * official record.
3245c51f124SMoriah Waterland */
3255c51f124SMoriah Waterland ext_ptr = (struct cfextra **)ar_next_avail(xspace);
3265c51f124SMoriah Waterland if (ext_ptr == NULL || *ext_ptr == NULL) {
3275c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY));
3285c51f124SMoriah Waterland return (NULL);
3295c51f124SMoriah Waterland }
3305c51f124SMoriah Waterland
3315c51f124SMoriah Waterland ext = *ext_ptr;
3325c51f124SMoriah Waterland ept = &(ext->cf_ent);
3335c51f124SMoriah Waterland
3345c51f124SMoriah Waterland /* Transfer what we just read in. */
3355c51f124SMoriah Waterland (void) memcpy(ept, &map_entry, sizeof (struct cfent));
3365c51f124SMoriah Waterland
3375c51f124SMoriah Waterland /* And process it into the cfextra structure. */
3385c51f124SMoriah Waterland if (pkgobjassign(ept,
3395c51f124SMoriah Waterland &(ext->server_local),
3405c51f124SMoriah Waterland &(ext->client_local),
3415c51f124SMoriah Waterland &(ext->server_path),
3425c51f124SMoriah Waterland &(ext->client_path),
3435c51f124SMoriah Waterland &(ext->map_path),
3445c51f124SMoriah Waterland mapflag, nc)) {
3455c51f124SMoriah Waterland /* It didn't take. */
3465c51f124SMoriah Waterland (void) ar_delete(xspace, eptnum);
3475c51f124SMoriah Waterland continue;
3485c51f124SMoriah Waterland }
3495c51f124SMoriah Waterland
3505c51f124SMoriah Waterland eptnum++;
3515c51f124SMoriah Waterland ext->fsys_value = BADFSYS; /* No file system data yet */
3525c51f124SMoriah Waterland ext->fsys_base = BADFSYS;
3535c51f124SMoriah Waterland }
3545c51f124SMoriah Waterland
3555c51f124SMoriah Waterland if (eptnum == 0) {
3565c51f124SMoriah Waterland logerr(gettext(WRN_NOPKGOBJ));
3575c51f124SMoriah Waterland return (NULL);
3585c51f124SMoriah Waterland }
3595c51f124SMoriah Waterland
3605c51f124SMoriah Waterland /* setup a pointer array to point to malloc'd entries space */
3615c51f124SMoriah Waterland extlist = (struct cfextra **)ar_get_head(xspace);
3625c51f124SMoriah Waterland if (extlist == NULL) {
3635c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY));
3645c51f124SMoriah Waterland return (NULL);
3655c51f124SMoriah Waterland }
3665c51f124SMoriah Waterland
3675c51f124SMoriah Waterland (void) sortentry(-1);
3685c51f124SMoriah Waterland for (i = 0; i < eptnum; /* void */) {
3695c51f124SMoriah Waterland if (!sortentry(i))
3705c51f124SMoriah Waterland i++;
3715c51f124SMoriah Waterland }
3725c51f124SMoriah Waterland
3735c51f124SMoriah Waterland return (errflg ? NULL : extlist);
3745c51f124SMoriah Waterland }
3755c51f124SMoriah Waterland
3765c51f124SMoriah Waterland /*
3775c51f124SMoriah Waterland * This function sorts the final list of cfextra entries. If index = -1, the
3785c51f124SMoriah Waterland * function is initialized. index = 0 doesn't get us anywhere because this
3795c51f124SMoriah Waterland * sorts against index-1. Positive natural index values are compared and
3805c51f124SMoriah Waterland * sorted into the array appropriately. Yes, it does seem we should use a
3815c51f124SMoriah Waterland * quicksort on the whole array or something. The apparent reason for taking
3825c51f124SMoriah Waterland * this approach is that there are enough special considerations to be
3835c51f124SMoriah Waterland * applied to each package object that inserting them one-by-one doesn't cost
3845c51f124SMoriah Waterland * that much.
3855c51f124SMoriah Waterland */
3865c51f124SMoriah Waterland static int
sortentry(int index)3875c51f124SMoriah Waterland sortentry(int index)
3885c51f124SMoriah Waterland {
3895c51f124SMoriah Waterland struct cfextra *ext;
3905c51f124SMoriah Waterland struct cfent *ept, *ept_i;
3915c51f124SMoriah Waterland static int last = 0;
3925c51f124SMoriah Waterland int i, n, j;
3935c51f124SMoriah Waterland int upper, lower;
3945c51f124SMoriah Waterland
3955c51f124SMoriah Waterland if (index == 0)
3965c51f124SMoriah Waterland return (0);
3975c51f124SMoriah Waterland else if (index < 0) {
3985c51f124SMoriah Waterland last = 0;
3995c51f124SMoriah Waterland return (0);
4005c51f124SMoriah Waterland }
4015c51f124SMoriah Waterland
4025c51f124SMoriah Waterland /*
4035c51f124SMoriah Waterland * Based on the index, this is the package object we're going to
4045c51f124SMoriah Waterland * review. It may stay where it is or it may be repositioned in the
4055c51f124SMoriah Waterland * array.
4065c51f124SMoriah Waterland */
4075c51f124SMoriah Waterland ext = extlist[index];
4085c51f124SMoriah Waterland ept = &(ext->cf_ent);
4095c51f124SMoriah Waterland
4105c51f124SMoriah Waterland /* quick comparison optimization for pre-sorted arrays */
4115c51f124SMoriah Waterland if (strcmp(ept->path, extlist[index-1]->cf_ent.path) > 0) {
4125c51f124SMoriah Waterland /* do nothing */
4135c51f124SMoriah Waterland last = index-1;
4145c51f124SMoriah Waterland return (0);
4155c51f124SMoriah Waterland }
4165c51f124SMoriah Waterland
4175c51f124SMoriah Waterland lower = 0; /* lower bound of the unsorted elements */
4185c51f124SMoriah Waterland upper = index; /* upper bound */
4195c51f124SMoriah Waterland i = last;
4205c51f124SMoriah Waterland do {
4215c51f124SMoriah Waterland /*
4225c51f124SMoriah Waterland * NOTE: This does a binary sort on path. There are lots of
4235c51f124SMoriah Waterland * other worthy items in the array, but path is the key into
4245c51f124SMoriah Waterland * the package database.
4255c51f124SMoriah Waterland */
4265c51f124SMoriah Waterland ept_i = &(extlist[i]->cf_ent);
4275c51f124SMoriah Waterland
4285c51f124SMoriah Waterland n = strcmp(ept->path, ept_i->path);
4295c51f124SMoriah Waterland if (n == 0) {
4305c51f124SMoriah Waterland if (!ckdup(ept, ept_i)) {
4315c51f124SMoriah Waterland /*
4325c51f124SMoriah Waterland * If the array was seeded then there are
4335c51f124SMoriah Waterland * bound to be occasional duplicates.
4345c51f124SMoriah Waterland * Otherwise, duplicates are definitely a
4355c51f124SMoriah Waterland * sign of major damage.
4365c51f124SMoriah Waterland */
4375c51f124SMoriah Waterland if (array_preloaded) {
4385c51f124SMoriah Waterland if (!dup_merg(ext, extlist[i])) {
4395c51f124SMoriah Waterland progerr(gettext(ERR_DUPPATH),
4405c51f124SMoriah Waterland ept->path);
4415c51f124SMoriah Waterland errflg++;
4425c51f124SMoriah Waterland }
4435c51f124SMoriah Waterland } else {
4445c51f124SMoriah Waterland progerr(gettext(ERR_DUPPATH),
4455c51f124SMoriah Waterland ept->path);
4465c51f124SMoriah Waterland errflg++;
4475c51f124SMoriah Waterland }
4485c51f124SMoriah Waterland }
4495c51f124SMoriah Waterland /* remove the entry at index */
4505c51f124SMoriah Waterland (void) ar_delete(xspace, index);
4515c51f124SMoriah Waterland
4525c51f124SMoriah Waterland eptnum--;
4535c51f124SMoriah Waterland return (1); /* Use this index again. */
4545c51f124SMoriah Waterland } else if (n < 0) {
4555c51f124SMoriah Waterland /*
4565c51f124SMoriah Waterland * The path of interest is smaller than the path
4575c51f124SMoriah Waterland * under test. Move down array using the method of
4585c51f124SMoriah Waterland * division
4595c51f124SMoriah Waterland */
4605c51f124SMoriah Waterland upper = i;
4615c51f124SMoriah Waterland i = lower + (upper-lower)/2;
4625c51f124SMoriah Waterland } else {
4635c51f124SMoriah Waterland /* Move up array */
4645c51f124SMoriah Waterland lower = i+1;
4655c51f124SMoriah Waterland i = upper - (upper-lower)/2 - 1;
4665c51f124SMoriah Waterland }
4675c51f124SMoriah Waterland } while (upper != lower);
4685c51f124SMoriah Waterland last = i = upper;
4695c51f124SMoriah Waterland
4705c51f124SMoriah Waterland /* expand to insert at i */
4715c51f124SMoriah Waterland for (j = index; j > i; j--)
4725c51f124SMoriah Waterland extlist[j] = extlist[j-1];
4735c51f124SMoriah Waterland
4745c51f124SMoriah Waterland extlist[i] = ext;
4755c51f124SMoriah Waterland
4765c51f124SMoriah Waterland return (0);
4775c51f124SMoriah Waterland }
4785c51f124SMoriah Waterland
4795c51f124SMoriah Waterland /* Return the number of blocks required by the package object provided. */
4805c51f124SMoriah Waterland static fsblkcnt_t
nblks(short fsys_entry,struct cfextra * ext)4815c51f124SMoriah Waterland nblks(short fsys_entry, struct cfextra *ext)
4825c51f124SMoriah Waterland {
4835c51f124SMoriah Waterland fsblkcnt_t blk;
4845c51f124SMoriah Waterland ulong_t block_size;
4855c51f124SMoriah Waterland ulong_t frag_size;
4865c51f124SMoriah Waterland
4875c51f124SMoriah Waterland block_size = (ulong_t)get_blk_size_n(fsys_entry);
4885c51f124SMoriah Waterland frag_size = (ulong_t)get_frag_size_n(fsys_entry);
4895c51f124SMoriah Waterland
4905c51f124SMoriah Waterland if (strchr("dxs", ext->cf_ent.ftype))
4915c51f124SMoriah Waterland blk =
4925c51f124SMoriah Waterland nblk(block_size, block_size, frag_size);
4935c51f124SMoriah Waterland else if (ext->cf_ent.cinfo.size != BADCONT)
4945c51f124SMoriah Waterland blk = nblk(ext->cf_ent.cinfo.size, block_size,
4955c51f124SMoriah Waterland frag_size);
4965c51f124SMoriah Waterland else
4975c51f124SMoriah Waterland blk = 0;
4985c51f124SMoriah Waterland
4995c51f124SMoriah Waterland return (blk);
5005c51f124SMoriah Waterland }
5015c51f124SMoriah Waterland
5025c51f124SMoriah Waterland /* Remove ext1 from the filesystem size calculations and add ext2. */
5035c51f124SMoriah Waterland static void
size_xchng(struct cfextra * ext1,struct cfextra * ext2)5045c51f124SMoriah Waterland size_xchng(struct cfextra *ext1, struct cfextra *ext2)
5055c51f124SMoriah Waterland {
5065c51f124SMoriah Waterland fsblkcnt_t bused;
5075c51f124SMoriah Waterland ulong_t block_size;
5085c51f124SMoriah Waterland ulong_t frag_size;
5095c51f124SMoriah Waterland fsblkcnt_t blks1, blks2;
5105c51f124SMoriah Waterland short fsys_entry;
5115c51f124SMoriah Waterland
5125c51f124SMoriah Waterland /*
5135c51f124SMoriah Waterland * Since these are on the same filesystem, either one will yield the
5145c51f124SMoriah Waterland * correct block and fragment size.
5155c51f124SMoriah Waterland */
5165c51f124SMoriah Waterland fsys_entry = ext1->fsys_base;
5175c51f124SMoriah Waterland block_size = (ulong_t)get_blk_size_n(fsys_entry);
5185c51f124SMoriah Waterland frag_size = (ulong_t)get_frag_size_n(fsys_entry);
5195c51f124SMoriah Waterland
5205c51f124SMoriah Waterland blks1 = nblk(ext1->cf_ent.cinfo.size, block_size, frag_size);
5215c51f124SMoriah Waterland blks2 = nblk(ext2->cf_ent.cinfo.size, block_size, frag_size);
5225c51f124SMoriah Waterland
5235c51f124SMoriah Waterland if (blks1 != blks2) {
5245c51f124SMoriah Waterland /* First, lose the old size, then add the new size. */
5255c51f124SMoriah Waterland bused = get_blk_used_n(fsys_entry);
5265c51f124SMoriah Waterland bused -= nblks(fsys_entry, ext1);
5275c51f124SMoriah Waterland bused += nblks(fsys_entry, ext2);
5285c51f124SMoriah Waterland
5295c51f124SMoriah Waterland set_blk_used_n(fsys_entry, bused);
5305c51f124SMoriah Waterland }
5315c51f124SMoriah Waterland }
5325c51f124SMoriah Waterland
5335c51f124SMoriah Waterland /*
5345c51f124SMoriah Waterland * This function merges duplicate non-directory entries resulting from a
5355c51f124SMoriah Waterland * dryrun or other procedure which preloads the extlist. It uses an odd
5365c51f124SMoriah Waterland * heuristic to determine which package object is newest: only package
5375c51f124SMoriah Waterland * objects from the dryrun file will have pinfo pointers. Therefore, the
5385c51f124SMoriah Waterland * object with a pinfo pointer is from the dryrun file and it will be
5395c51f124SMoriah Waterland * overwritten by the object being installed by this package.
5405c51f124SMoriah Waterland *
5415c51f124SMoriah Waterland * Assumptions:
5425c51f124SMoriah Waterland * 1. The newer object will be overwriting the older object.
5435c51f124SMoriah Waterland * 2. The two objects are close enough to the same size that
5445c51f124SMoriah Waterland * the sizing is still OK.
5455c51f124SMoriah Waterland *
5465c51f124SMoriah Waterland * The calling routine will overwrite ept1, so this must return ept2 with
5475c51f124SMoriah Waterland * the correct data to keep. There being only one logical outcome of a
5485c51f124SMoriah Waterland * failure, this returns 1 for OK and 0 for FAIL.
5495c51f124SMoriah Waterland */
5505c51f124SMoriah Waterland static int
dup_merg(struct cfextra * ext1,struct cfextra * ext2)5515c51f124SMoriah Waterland dup_merg(struct cfextra *ext1, struct cfextra *ext2)
5525c51f124SMoriah Waterland {
5535c51f124SMoriah Waterland struct cfent *ept1, *ept2;
5545c51f124SMoriah Waterland
5555c51f124SMoriah Waterland ept1 = &(ext1->cf_ent);
5565c51f124SMoriah Waterland ept2 = &(ext2->cf_ent);
5575c51f124SMoriah Waterland
5585c51f124SMoriah Waterland if (strchr("?dx", ept1->ftype))
5595c51f124SMoriah Waterland return (0);
5605c51f124SMoriah Waterland
5615c51f124SMoriah Waterland if (strchr("?dx", ept2->ftype))
5625c51f124SMoriah Waterland return (0);
5635c51f124SMoriah Waterland
5645c51f124SMoriah Waterland /* First, which is the eldest? */
5655c51f124SMoriah Waterland if (ext2->mstat.preloaded) {
5665c51f124SMoriah Waterland /*
5675c51f124SMoriah Waterland * While ept2 has the correct pinfo list (it was preloaded into
5685c51f124SMoriah Waterland * the array before the pkgmap was read), ept1 has everything
5695c51f124SMoriah Waterland * else. Here we copy the guts of ept1 into ept2.
5705c51f124SMoriah Waterland *
5715c51f124SMoriah Waterland * Start by grabbing the pointers to the ext2 items that we
5725c51f124SMoriah Waterland * need to either restore or free.
5735c51f124SMoriah Waterland */
5745c51f124SMoriah Waterland /* to free() */
5755c51f124SMoriah Waterland char *path = ept2->path;
5765c51f124SMoriah Waterland char *local = ept2->ainfo.local;
5775c51f124SMoriah Waterland
5785c51f124SMoriah Waterland /* to preserve */
5795c51f124SMoriah Waterland short npkgs = ept2->npkgs;
5805c51f124SMoriah Waterland struct pinfo *pinfo = ept2->pinfo;
5815c51f124SMoriah Waterland
5825c51f124SMoriah Waterland /* Copy everything from the new entry to the old */
5835c51f124SMoriah Waterland (void) memcpy(ept2, ept1, sizeof (struct cfent));
5845c51f124SMoriah Waterland
5855c51f124SMoriah Waterland /* Now restore the original stuff.. */
5865c51f124SMoriah Waterland ept2->path = path;
5875c51f124SMoriah Waterland ept2->ainfo.local = local;
5885c51f124SMoriah Waterland ept2->npkgs = npkgs;
5895c51f124SMoriah Waterland ept2->pinfo = pinfo;
5905c51f124SMoriah Waterland
5915c51f124SMoriah Waterland size_xchng(ext2, ext1);
5925c51f124SMoriah Waterland } else if (ext1->mstat.preloaded) {
5935c51f124SMoriah Waterland /*
5945c51f124SMoriah Waterland * ept2 is already the one we will keep. All we have to do is
5955c51f124SMoriah Waterland * copy over the pinfo pointer.
5965c51f124SMoriah Waterland */
5975c51f124SMoriah Waterland ept2->pinfo = ept1->pinfo;
5985c51f124SMoriah Waterland size_xchng(ext1, ext2);
5995c51f124SMoriah Waterland } else
6005c51f124SMoriah Waterland return (0);
6015c51f124SMoriah Waterland
6025c51f124SMoriah Waterland return (1);
6035c51f124SMoriah Waterland }
6045c51f124SMoriah Waterland
6055c51f124SMoriah Waterland /*
6065c51f124SMoriah Waterland * Check duplicate entries in the package object list. If it's a directory,
6075c51f124SMoriah Waterland * this just merges them, if not, it returns a 0 to force further processing.
6085c51f124SMoriah Waterland */
6095c51f124SMoriah Waterland static int
ckdup(struct cfent * ept1,struct cfent * ept2)6105c51f124SMoriah Waterland ckdup(struct cfent *ept1, struct cfent *ept2)
6115c51f124SMoriah Waterland {
6125c51f124SMoriah Waterland /* ept2 will be modified to contain "merged" entries */
6135c51f124SMoriah Waterland
6145c51f124SMoriah Waterland if (!strchr("?dx", ept1->ftype))
6155c51f124SMoriah Waterland return (0);
6165c51f124SMoriah Waterland
6175c51f124SMoriah Waterland if (!strchr("?dx", ept2->ftype))
6185c51f124SMoriah Waterland return (0);
6195c51f124SMoriah Waterland
6205c51f124SMoriah Waterland if (ept2->ainfo.mode == BADMODE)
6215c51f124SMoriah Waterland ept2->ainfo.mode = ept1->ainfo.mode;
6225c51f124SMoriah Waterland if ((ept1->ainfo.mode != ept2->ainfo.mode) &&
6235c51f124SMoriah Waterland (ept1->ainfo.mode != BADMODE))
6245c51f124SMoriah Waterland return (0);
6255c51f124SMoriah Waterland
6265c51f124SMoriah Waterland if (strcmp(ept2->ainfo.owner, "?") == 0)
6275c51f124SMoriah Waterland (void) strlcpy(ept2->ainfo.owner, ept1->ainfo.owner,
6285c51f124SMoriah Waterland sizeof (ept2->ainfo.owner));
6295c51f124SMoriah Waterland if (strcmp(ept1->ainfo.owner, ept2->ainfo.owner) &&
6305c51f124SMoriah Waterland strcmp(ept1->ainfo.owner, "?"))
6315c51f124SMoriah Waterland return (0);
6325c51f124SMoriah Waterland
6335c51f124SMoriah Waterland if (strcmp(ept2->ainfo.group, "?") == 0)
6345c51f124SMoriah Waterland (void) strlcpy(ept2->ainfo.group, ept1->ainfo.group,
6355c51f124SMoriah Waterland sizeof (ept2->ainfo.group));
6365c51f124SMoriah Waterland if (strcmp(ept1->ainfo.group, ept2->ainfo.group) &&
6375c51f124SMoriah Waterland strcmp(ept1->ainfo.group, "?"))
6385c51f124SMoriah Waterland return (0);
6395c51f124SMoriah Waterland
6405c51f124SMoriah Waterland if (ept1->pinfo) {
6415c51f124SMoriah Waterland ept2->npkgs = ept1->npkgs;
6425c51f124SMoriah Waterland ept2->pinfo = ept1->pinfo;
6435c51f124SMoriah Waterland }
6445c51f124SMoriah Waterland
6455c51f124SMoriah Waterland return (1);
6465c51f124SMoriah Waterland }
6475c51f124SMoriah Waterland
6485c51f124SMoriah Waterland /*
6495c51f124SMoriah Waterland * Replace the old package database entry with the new one preserving the
6505c51f124SMoriah Waterland * data which remains constant across the replacement.
6515c51f124SMoriah Waterland * copied directly:
6525c51f124SMoriah Waterland * ftype, pkg_class
6535c51f124SMoriah Waterland *
6545c51f124SMoriah Waterland * preserved from old:
6555c51f124SMoriah Waterland * path, npkgs, pinfo
6565c51f124SMoriah Waterland */
6575c51f124SMoriah Waterland void
repl_cfent(struct cfent * new,struct cfent * old)6585c51f124SMoriah Waterland repl_cfent(struct cfent *new, struct cfent *old)
6595c51f124SMoriah Waterland {
6605c51f124SMoriah Waterland char *path = old->path;
6615c51f124SMoriah Waterland short npkgs = old->npkgs;
6625c51f124SMoriah Waterland struct pinfo *pinfo = old->pinfo;
6635c51f124SMoriah Waterland
6645c51f124SMoriah Waterland /* Copy everything from the new entry over */
6655c51f124SMoriah Waterland (void) memcpy(old, new, sizeof (struct cfent));
6665c51f124SMoriah Waterland
6675c51f124SMoriah Waterland if (strchr("sl", new->ftype) == NULL)
6685c51f124SMoriah Waterland old->ainfo.local = NULL;
6695c51f124SMoriah Waterland
6705c51f124SMoriah Waterland old->path = path;
6715c51f124SMoriah Waterland old->npkgs = npkgs;
6725c51f124SMoriah Waterland old->pinfo = pinfo;
6735c51f124SMoriah Waterland
6745c51f124SMoriah Waterland old->volno = 0;
6755c51f124SMoriah Waterland }
6765c51f124SMoriah Waterland
6775c51f124SMoriah Waterland /*
6785c51f124SMoriah Waterland * Copy critical portions of cf_ent (from the package database) and el_ent
6795c51f124SMoriah Waterland * (constructed from the pkgmap) into a merged cfent structure, tp. Then copy
6805c51f124SMoriah Waterland * that to the el_ent structure. The approach we take here is to copy over
6815c51f124SMoriah Waterland * everything from the package database entry, condition the paths based upon
6825c51f124SMoriah Waterland * the currently installed path and then insert the following entries from
6835c51f124SMoriah Waterland * the new structure :
6845c51f124SMoriah Waterland * cfent.volno
6855c51f124SMoriah Waterland * pkg_class
6865c51f124SMoriah Waterland * pkg_class_idx
6875c51f124SMoriah Waterland *
6885c51f124SMoriah Waterland * The pinfo list is then copied from the cfent list. While
6895c51f124SMoriah Waterland * fsys_value is also copied over, it hasn't been set yet. This function
6905c51f124SMoriah Waterland * copies over whatever the default value is from the new structure.
6915c51f124SMoriah Waterland *
6925c51f124SMoriah Waterland * The copied entry is returned in the el_ent argument and the function
6935c51f124SMoriah Waterland * value is 1 on success, 0 on failure. There is no recovery plan for
6945c51f124SMoriah Waterland * failure.
6955c51f124SMoriah Waterland */
6965c51f124SMoriah Waterland int
cp_cfent(struct cfent * cf_ent,struct cfextra * el_ent)6975c51f124SMoriah Waterland cp_cfent(struct cfent *cf_ent, struct cfextra *el_ent)
6985c51f124SMoriah Waterland {
6995c51f124SMoriah Waterland struct cfextra *tp;
7005c51f124SMoriah Waterland
7015c51f124SMoriah Waterland /* Allocate space for cfent copy */
7025c51f124SMoriah Waterland if ((tp = (struct cfextra *)calloc(1,
7035c51f124SMoriah Waterland sizeof (struct cfextra))) == NULL) {
7045c51f124SMoriah Waterland progerr(gettext("cp_cfent: memory allocation error"));
7055c51f124SMoriah Waterland return (0);
7065c51f124SMoriah Waterland }
7075c51f124SMoriah Waterland
7085c51f124SMoriah Waterland /* Copy everything from the package database over */
7095c51f124SMoriah Waterland (void) memcpy(&(tp->cf_ent), cf_ent, sizeof (struct cfent));
7105c51f124SMoriah Waterland
7115c51f124SMoriah Waterland /* Now overlay new items from the pkgmap */
7125c51f124SMoriah Waterland tp->fsys_value = el_ent->fsys_value;
7135c51f124SMoriah Waterland tp->cf_ent.volno = el_ent->cf_ent.volno;
7145c51f124SMoriah Waterland (void) strlcpy(tp->cf_ent.pkg_class, el_ent->cf_ent.pkg_class,
7155c51f124SMoriah Waterland sizeof (tp->cf_ent.pkg_class));
7165c51f124SMoriah Waterland tp->cf_ent.pkg_class_idx = el_ent->cf_ent.pkg_class_idx;
7175c51f124SMoriah Waterland tp->cf_ent.pinfo = cf_ent->pinfo;
7185c51f124SMoriah Waterland
7195c51f124SMoriah Waterland /*
7205c51f124SMoriah Waterland * The paths are identical, so we get them from the new entry. These
7215c51f124SMoriah Waterland * are pointing to a malloc'd section of memory containing a string
7225c51f124SMoriah Waterland * that we aren't moving in this operation, so everybody points to
7235c51f124SMoriah Waterland * the same thing during these transfers.
7245c51f124SMoriah Waterland */
7255c51f124SMoriah Waterland tp->cf_ent.path = el_ent->client_path;
7265c51f124SMoriah Waterland tp->server_path = el_ent->server_path;
7275c51f124SMoriah Waterland tp->client_path = el_ent->client_path;
7285c51f124SMoriah Waterland tp->map_path = el_ent->map_path;
7295c51f124SMoriah Waterland
7305c51f124SMoriah Waterland /*
7315c51f124SMoriah Waterland * Since instvol() expects to work with the *original* mstat data,
7325c51f124SMoriah Waterland * mstat is just copied here. NOTE: mstat looks like a structure, but
7335c51f124SMoriah Waterland * it's really a short bit array.
7345c51f124SMoriah Waterland */
7355c51f124SMoriah Waterland tp->mstat = el_ent->mstat;
7365c51f124SMoriah Waterland
7375c51f124SMoriah Waterland /* Copy everything from the temporary structure to the new entry */
7385c51f124SMoriah Waterland (void) memcpy(el_ent, tp, sizeof (struct cfextra));
7395c51f124SMoriah Waterland free(tp);
7405c51f124SMoriah Waterland
7415c51f124SMoriah Waterland return (1);
7425c51f124SMoriah Waterland }
743