1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland #include <stdio.h> 29*5c51f124SMoriah Waterland #include <limits.h> 30*5c51f124SMoriah Waterland #include <stdlib.h> 31*5c51f124SMoriah Waterland #include <unistd.h> 32*5c51f124SMoriah Waterland #include <errno.h> 33*5c51f124SMoriah Waterland #include <string.h> 34*5c51f124SMoriah Waterland #include <sys/types.h> 35*5c51f124SMoriah Waterland #include <pkgstrct.h> 36*5c51f124SMoriah Waterland #include <locale.h> 37*5c51f124SMoriah Waterland #include <libintl.h> 38*5c51f124SMoriah Waterland #include <pkglib.h> 39*5c51f124SMoriah Waterland #include <install.h> 40*5c51f124SMoriah Waterland #include <libinst.h> 41*5c51f124SMoriah Waterland 42*5c51f124SMoriah Waterland #define WRN_NOPKGOBJ "WARNING: no package objects found" 43*5c51f124SMoriah Waterland 44*5c51f124SMoriah Waterland #define ERR_MEMORY "memory allocation failure" 45*5c51f124SMoriah Waterland #define ERR_DUPPATH "duplicate pathname <%s>" 46*5c51f124SMoriah Waterland 47*5c51f124SMoriah Waterland /* libpkg/gpkgmap */ 48*5c51f124SMoriah Waterland extern int getmapmode(void); 49*5c51f124SMoriah Waterland 50*5c51f124SMoriah Waterland #define EPTMALLOC 512 51*5c51f124SMoriah Waterland 52*5c51f124SMoriah Waterland static struct cfextra **extlist; 53*5c51f124SMoriah Waterland 54*5c51f124SMoriah Waterland int eptnum; 55*5c51f124SMoriah Waterland static int array_preloaded = 0; 56*5c51f124SMoriah Waterland static int errflg; 57*5c51f124SMoriah Waterland static int nparts; 58*5c51f124SMoriah Waterland static int xspace = -1; 59*5c51f124SMoriah Waterland 60*5c51f124SMoriah Waterland void pkgobjinit(void); 61*5c51f124SMoriah Waterland static int pkgobjassign(struct cfent *ept, char **server_local, 62*5c51f124SMoriah Waterland char **client_local, char **server_path, 63*5c51f124SMoriah Waterland char **client_path, char **map_path, int mapflag, 64*5c51f124SMoriah Waterland int nc); 65*5c51f124SMoriah Waterland 66*5c51f124SMoriah Waterland static int ckdup(struct cfent *ept1, struct cfent *ept2); 67*5c51f124SMoriah Waterland static int sortentry(int index); 68*5c51f124SMoriah Waterland static int dup_merg(struct cfextra *ext1, struct cfextra *ext2); 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland void 71*5c51f124SMoriah Waterland pkgobjinit(void) 72*5c51f124SMoriah Waterland { 73*5c51f124SMoriah Waterland if (array_preloaded) /* Already done. */ 74*5c51f124SMoriah Waterland return; 75*5c51f124SMoriah Waterland 76*5c51f124SMoriah Waterland errflg = nparts = eptnum = 0; 77*5c51f124SMoriah Waterland 78*5c51f124SMoriah Waterland if (xspace != -1) { 79*5c51f124SMoriah Waterland ar_free(xspace); 80*5c51f124SMoriah Waterland xspace = -1; 81*5c51f124SMoriah Waterland } 82*5c51f124SMoriah Waterland 83*5c51f124SMoriah Waterland /* 84*5c51f124SMoriah Waterland * initialize dynamic memory used to store 85*5c51f124SMoriah Waterland * path information which is read in 86*5c51f124SMoriah Waterland */ 87*5c51f124SMoriah Waterland (void) pathdup((char *)0); 88*5c51f124SMoriah Waterland } 89*5c51f124SMoriah Waterland 90*5c51f124SMoriah Waterland /* 91*5c51f124SMoriah Waterland * This function assigns appropriate values based upon the pkgmap entry 92*5c51f124SMoriah Waterland * in the cfent structure. 93*5c51f124SMoriah Waterland */ 94*5c51f124SMoriah Waterland static int 95*5c51f124SMoriah Waterland pkgobjassign(struct cfent *ept, char **server_local, char **client_local, 96*5c51f124SMoriah Waterland char **server_path, char **client_path, char **map_path, int mapflag, 97*5c51f124SMoriah Waterland int nc) 98*5c51f124SMoriah Waterland { 99*5c51f124SMoriah Waterland int path_duped = 0; 100*5c51f124SMoriah Waterland int local_duped = 0; 101*5c51f124SMoriah Waterland char source[PATH_MAX+1]; 102*5c51f124SMoriah Waterland 103*5c51f124SMoriah Waterland if (nc >= 0 && ept->ftype != 'i') 104*5c51f124SMoriah Waterland if ((ept->pkg_class_idx = cl_idx(ept->pkg_class)) == -1) 105*5c51f124SMoriah Waterland return (1); 106*5c51f124SMoriah Waterland 107*5c51f124SMoriah Waterland if (ept->volno > nparts) 108*5c51f124SMoriah Waterland nparts++; 109*5c51f124SMoriah Waterland 110*5c51f124SMoriah Waterland /* 111*5c51f124SMoriah Waterland * Generate local (delivered source) paths for files 112*5c51f124SMoriah Waterland * which need them so that the install routine will know 113*5c51f124SMoriah Waterland * where to get the file from the package. Note that we 114*5c51f124SMoriah Waterland * do not resolve path environment variables here since 115*5c51f124SMoriah Waterland * they won't be resolved in the reloc directory. 116*5c51f124SMoriah Waterland */ 117*5c51f124SMoriah Waterland if ((mapflag > 1) && strchr("fve", ept->ftype)) { 118*5c51f124SMoriah Waterland if (ept->ainfo.local == NULL) { 119*5c51f124SMoriah Waterland source[0] = '~'; 120*5c51f124SMoriah Waterland (void) strlcpy(&source[1], ept->path, 121*5c51f124SMoriah Waterland sizeof (source)-1); 122*5c51f124SMoriah Waterland ept->ainfo.local = pathdup(source); 123*5c51f124SMoriah Waterland *server_local = ept->ainfo.local; 124*5c51f124SMoriah Waterland *client_local = ept->ainfo.local; 125*5c51f124SMoriah Waterland 126*5c51f124SMoriah Waterland local_duped = 1; 127*5c51f124SMoriah Waterland } 128*5c51f124SMoriah Waterland } 129*5c51f124SMoriah Waterland 130*5c51f124SMoriah Waterland /* 131*5c51f124SMoriah Waterland * Evaluate the destination path based upon available 132*5c51f124SMoriah Waterland * environment, then produce a client-relative and 133*5c51f124SMoriah Waterland * server-relative canonized path. 134*5c51f124SMoriah Waterland */ 135*5c51f124SMoriah Waterland if (mapflag && (ept->ftype != 'i')) { 136*5c51f124SMoriah Waterland mappath(getmapmode(), ept->path); /* evaluate variables */ 137*5c51f124SMoriah Waterland canonize(ept->path); /* Fix path as necessary. */ 138*5c51f124SMoriah Waterland 139*5c51f124SMoriah Waterland (void) eval_path(server_path, 140*5c51f124SMoriah Waterland client_path, 141*5c51f124SMoriah Waterland map_path, 142*5c51f124SMoriah Waterland ept->path); 143*5c51f124SMoriah Waterland path_duped = 1; /* eval_path dup's it */ 144*5c51f124SMoriah Waterland ept->path = *server_path; /* default */ 145*5c51f124SMoriah Waterland } 146*5c51f124SMoriah Waterland 147*5c51f124SMoriah Waterland /* 148*5c51f124SMoriah Waterland * Deal with source for hard and soft links. 149*5c51f124SMoriah Waterland */ 150*5c51f124SMoriah Waterland if (strchr("sl", ept->ftype)) { 151*5c51f124SMoriah Waterland if (mapflag) { 152*5c51f124SMoriah Waterland mappath(getmapmode(), ept->ainfo.local); 153*5c51f124SMoriah Waterland if (!RELATIVE(ept->ainfo.local)) { 154*5c51f124SMoriah Waterland canonize(ept->ainfo.local); 155*5c51f124SMoriah Waterland 156*5c51f124SMoriah Waterland /* check for hard link */ 157*5c51f124SMoriah Waterland if (ept->ftype == 'l') { 158*5c51f124SMoriah Waterland (void) eval_path( 159*5c51f124SMoriah Waterland server_local, 160*5c51f124SMoriah Waterland client_local, 161*5c51f124SMoriah Waterland NULL, 162*5c51f124SMoriah Waterland ept->ainfo.local); 163*5c51f124SMoriah Waterland local_duped = 1; 164*5c51f124SMoriah Waterland 165*5c51f124SMoriah Waterland /* Default to server. */ 166*5c51f124SMoriah Waterland ept->ainfo.local = *server_local; 167*5c51f124SMoriah Waterland } 168*5c51f124SMoriah Waterland } 169*5c51f124SMoriah Waterland } 170*5c51f124SMoriah Waterland } 171*5c51f124SMoriah Waterland 172*5c51f124SMoriah Waterland /* 173*5c51f124SMoriah Waterland * For the paths (both source and target) that were too mundane to 174*5c51f124SMoriah Waterland * have been copied into dup space yet, do that. 175*5c51f124SMoriah Waterland */ 176*5c51f124SMoriah Waterland if (!path_duped) { 177*5c51f124SMoriah Waterland *server_path = pathdup(ept->path); 178*5c51f124SMoriah Waterland *client_path = *server_path; 179*5c51f124SMoriah Waterland ept->path = *server_path; 180*5c51f124SMoriah Waterland 181*5c51f124SMoriah Waterland path_duped = 1; 182*5c51f124SMoriah Waterland } 183*5c51f124SMoriah Waterland if (ept->ainfo.local != NULL) 184*5c51f124SMoriah Waterland if (!local_duped) { 185*5c51f124SMoriah Waterland *server_local = pathdup(ept->ainfo.local); 186*5c51f124SMoriah Waterland ept->ainfo.local = *server_local; 187*5c51f124SMoriah Waterland *client_local = ept->ainfo.local; 188*5c51f124SMoriah Waterland 189*5c51f124SMoriah Waterland local_duped = 1; 190*5c51f124SMoriah Waterland } 191*5c51f124SMoriah Waterland 192*5c51f124SMoriah Waterland return (0); 193*5c51f124SMoriah Waterland } 194*5c51f124SMoriah Waterland 195*5c51f124SMoriah Waterland /* This initializes the package object array. */ 196*5c51f124SMoriah Waterland int 197*5c51f124SMoriah Waterland init_pkgobjspace(void) 198*5c51f124SMoriah Waterland { 199*5c51f124SMoriah Waterland if (array_preloaded) /* Already done. */ 200*5c51f124SMoriah Waterland return (1); 201*5c51f124SMoriah Waterland 202*5c51f124SMoriah Waterland if (xspace == -1) { 203*5c51f124SMoriah Waterland xspace = ar_create(EPTMALLOC, sizeof (struct cfextra), 204*5c51f124SMoriah Waterland "package object"); 205*5c51f124SMoriah Waterland if (xspace == -1) { 206*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY)); 207*5c51f124SMoriah Waterland return (0); 208*5c51f124SMoriah Waterland } 209*5c51f124SMoriah Waterland } 210*5c51f124SMoriah Waterland 211*5c51f124SMoriah Waterland return (1); 212*5c51f124SMoriah Waterland } 213*5c51f124SMoriah Waterland 214*5c51f124SMoriah Waterland int 215*5c51f124SMoriah Waterland seed_pkgobjmap(struct cfextra *ext_entry, char *path, char *local) 216*5c51f124SMoriah Waterland { 217*5c51f124SMoriah Waterland struct cfextra *ext, **ext_ptr; 218*5c51f124SMoriah Waterland 219*5c51f124SMoriah Waterland /* offsets for the various path images. */ 220*5c51f124SMoriah Waterland int client_path_os; 221*5c51f124SMoriah Waterland int server_path_os; 222*5c51f124SMoriah Waterland int map_path_os; 223*5c51f124SMoriah Waterland int client_local_os; 224*5c51f124SMoriah Waterland int server_local_os; 225*5c51f124SMoriah Waterland 226*5c51f124SMoriah Waterland ext_ptr = (struct cfextra **)ar_next_avail(xspace); 227*5c51f124SMoriah Waterland 228*5c51f124SMoriah Waterland if (ext_ptr == NULL || *ext_ptr == NULL) { 229*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY)); 230*5c51f124SMoriah Waterland return (NULL); 231*5c51f124SMoriah Waterland } 232*5c51f124SMoriah Waterland 233*5c51f124SMoriah Waterland ext = *ext_ptr; 234*5c51f124SMoriah Waterland 235*5c51f124SMoriah Waterland (void) memcpy(ext, ext_entry, sizeof (struct cfextra)); 236*5c51f124SMoriah Waterland 237*5c51f124SMoriah Waterland /* Figure out all of the offsets. */ 238*5c51f124SMoriah Waterland client_path_os = ((ptrdiff_t)ext->client_path - 239*5c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path); 240*5c51f124SMoriah Waterland server_path_os = ((ptrdiff_t)ext->server_path - 241*5c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path); 242*5c51f124SMoriah Waterland map_path_os = ((ptrdiff_t)ext->map_path - 243*5c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.path); 244*5c51f124SMoriah Waterland client_local_os = ((ptrdiff_t)ext->client_local - 245*5c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.ainfo.local); 246*5c51f124SMoriah Waterland server_local_os = ((ptrdiff_t)ext->server_local - 247*5c51f124SMoriah Waterland (ptrdiff_t)ext->cf_ent.ainfo.local); 248*5c51f124SMoriah Waterland 249*5c51f124SMoriah Waterland /* Allocate and store the path name. */ 250*5c51f124SMoriah Waterland ext->cf_ent.path = pathdup(path); 251*5c51f124SMoriah Waterland 252*5c51f124SMoriah Waterland /* Assign the path substring pointers. */ 253*5c51f124SMoriah Waterland ext->client_path = (ext->cf_ent.path + client_path_os); 254*5c51f124SMoriah Waterland ext->server_path = (ext->cf_ent.path + server_path_os); 255*5c51f124SMoriah Waterland ext->map_path = (ext->cf_ent.path + map_path_os); 256*5c51f124SMoriah Waterland 257*5c51f124SMoriah Waterland /* If there's a local entry, allocate and store it as well. */ 258*5c51f124SMoriah Waterland if (local) { 259*5c51f124SMoriah Waterland ext->cf_ent.ainfo.local = pathdup(local); 260*5c51f124SMoriah Waterland 261*5c51f124SMoriah Waterland ext->client_local = (ext->cf_ent.ainfo.local + client_local_os); 262*5c51f124SMoriah Waterland ext->server_local = (ext->cf_ent.ainfo.local + server_local_os); 263*5c51f124SMoriah Waterland } else { 264*5c51f124SMoriah Waterland ext->cf_ent.ainfo.local = NULL; 265*5c51f124SMoriah Waterland ext->client_local = NULL; 266*5c51f124SMoriah Waterland ext->server_local = NULL; 267*5c51f124SMoriah Waterland } 268*5c51f124SMoriah Waterland 269*5c51f124SMoriah Waterland eptnum++; 270*5c51f124SMoriah Waterland array_preloaded = 1; 271*5c51f124SMoriah Waterland 272*5c51f124SMoriah Waterland return (0); 273*5c51f124SMoriah Waterland } 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland /* 276*5c51f124SMoriah Waterland * This function reads the pkgmap (or any file similarly formatted) and 277*5c51f124SMoriah Waterland * returns a pointer to a list of struct cfextra (each of which 278*5c51f124SMoriah Waterland * contains a struct cfent) representing the contents of that file. 279*5c51f124SMoriah Waterland */ 280*5c51f124SMoriah Waterland 281*5c51f124SMoriah Waterland /* ARGSUSED ir in pkgobjmap */ 282*5c51f124SMoriah Waterland struct cfextra ** 283*5c51f124SMoriah Waterland pkgobjmap(VFP_T *vfp, int mapflag, char *ir) 284*5c51f124SMoriah Waterland { 285*5c51f124SMoriah Waterland struct cfextra *ext, **ext_ptr; 286*5c51f124SMoriah Waterland struct cfent *ept, map_entry; 287*5c51f124SMoriah Waterland int i; 288*5c51f124SMoriah Waterland int n; 289*5c51f124SMoriah Waterland int nc; 290*5c51f124SMoriah Waterland 291*5c51f124SMoriah Waterland pkgobjinit(); 292*5c51f124SMoriah Waterland if (!init_pkgobjspace()) 293*5c51f124SMoriah Waterland quit(99); 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland nc = cl_getn(); 296*5c51f124SMoriah Waterland for (;;) { 297*5c51f124SMoriah Waterland /* Clear the buffer. */ 298*5c51f124SMoriah Waterland (void) memset(&map_entry, '\000', sizeof (struct cfent)); 299*5c51f124SMoriah Waterland 300*5c51f124SMoriah Waterland /* 301*5c51f124SMoriah Waterland * Fill in a cfent structure in a very preliminary fashion. 302*5c51f124SMoriah Waterland * ept->path and ept->ainfo.local point to static memory 303*5c51f124SMoriah Waterland * areas of size PATH_MAX. These are manipulated and 304*5c51f124SMoriah Waterland * then provided their own allocations later in this function. 305*5c51f124SMoriah Waterland */ 306*5c51f124SMoriah Waterland n = gpkgmapvfp(&map_entry, vfp); 307*5c51f124SMoriah Waterland 308*5c51f124SMoriah Waterland if (n == 0) 309*5c51f124SMoriah Waterland break; /* no more entries in pkgmap */ 310*5c51f124SMoriah Waterland else if (n < 0) { 311*5c51f124SMoriah Waterland char *errstr = getErrstr(); 312*5c51f124SMoriah Waterland progerr(gettext("bad entry read in pkgmap")); 313*5c51f124SMoriah Waterland logerr(gettext("pathname=%s"), 314*5c51f124SMoriah Waterland (map_entry.path && *map_entry.path) ? 315*5c51f124SMoriah Waterland map_entry.path : "Unknown"); 316*5c51f124SMoriah Waterland logerr(gettext("problem=%s"), 317*5c51f124SMoriah Waterland (errstr && *errstr) ? errstr : "Unknown"); 318*5c51f124SMoriah Waterland return (NULL); 319*5c51f124SMoriah Waterland } 320*5c51f124SMoriah Waterland 321*5c51f124SMoriah Waterland /* 322*5c51f124SMoriah Waterland * A valid entry was found in the map, so allocate an 323*5c51f124SMoriah Waterland * official record. 324*5c51f124SMoriah Waterland */ 325*5c51f124SMoriah Waterland ext_ptr = (struct cfextra **)ar_next_avail(xspace); 326*5c51f124SMoriah Waterland if (ext_ptr == NULL || *ext_ptr == NULL) { 327*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY)); 328*5c51f124SMoriah Waterland return (NULL); 329*5c51f124SMoriah Waterland } 330*5c51f124SMoriah Waterland 331*5c51f124SMoriah Waterland ext = *ext_ptr; 332*5c51f124SMoriah Waterland ept = &(ext->cf_ent); 333*5c51f124SMoriah Waterland 334*5c51f124SMoriah Waterland /* Transfer what we just read in. */ 335*5c51f124SMoriah Waterland (void) memcpy(ept, &map_entry, sizeof (struct cfent)); 336*5c51f124SMoriah Waterland 337*5c51f124SMoriah Waterland /* And process it into the cfextra structure. */ 338*5c51f124SMoriah Waterland if (pkgobjassign(ept, 339*5c51f124SMoriah Waterland &(ext->server_local), 340*5c51f124SMoriah Waterland &(ext->client_local), 341*5c51f124SMoriah Waterland &(ext->server_path), 342*5c51f124SMoriah Waterland &(ext->client_path), 343*5c51f124SMoriah Waterland &(ext->map_path), 344*5c51f124SMoriah Waterland mapflag, nc)) { 345*5c51f124SMoriah Waterland /* It didn't take. */ 346*5c51f124SMoriah Waterland (void) ar_delete(xspace, eptnum); 347*5c51f124SMoriah Waterland continue; 348*5c51f124SMoriah Waterland } 349*5c51f124SMoriah Waterland 350*5c51f124SMoriah Waterland eptnum++; 351*5c51f124SMoriah Waterland ext->fsys_value = BADFSYS; /* No file system data yet */ 352*5c51f124SMoriah Waterland ext->fsys_base = BADFSYS; 353*5c51f124SMoriah Waterland } 354*5c51f124SMoriah Waterland 355*5c51f124SMoriah Waterland if (eptnum == 0) { 356*5c51f124SMoriah Waterland logerr(gettext(WRN_NOPKGOBJ)); 357*5c51f124SMoriah Waterland return (NULL); 358*5c51f124SMoriah Waterland } 359*5c51f124SMoriah Waterland 360*5c51f124SMoriah Waterland /* setup a pointer array to point to malloc'd entries space */ 361*5c51f124SMoriah Waterland extlist = (struct cfextra **)ar_get_head(xspace); 362*5c51f124SMoriah Waterland if (extlist == NULL) { 363*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY)); 364*5c51f124SMoriah Waterland return (NULL); 365*5c51f124SMoriah Waterland } 366*5c51f124SMoriah Waterland 367*5c51f124SMoriah Waterland (void) sortentry(-1); 368*5c51f124SMoriah Waterland for (i = 0; i < eptnum; /* void */) { 369*5c51f124SMoriah Waterland if (!sortentry(i)) 370*5c51f124SMoriah Waterland i++; 371*5c51f124SMoriah Waterland } 372*5c51f124SMoriah Waterland 373*5c51f124SMoriah Waterland return (errflg ? NULL : extlist); 374*5c51f124SMoriah Waterland } 375*5c51f124SMoriah Waterland 376*5c51f124SMoriah Waterland /* 377*5c51f124SMoriah Waterland * This function sorts the final list of cfextra entries. If index = -1, the 378*5c51f124SMoriah Waterland * function is initialized. index = 0 doesn't get us anywhere because this 379*5c51f124SMoriah Waterland * sorts against index-1. Positive natural index values are compared and 380*5c51f124SMoriah Waterland * sorted into the array appropriately. Yes, it does seem we should use a 381*5c51f124SMoriah Waterland * quicksort on the whole array or something. The apparent reason for taking 382*5c51f124SMoriah Waterland * this approach is that there are enough special considerations to be 383*5c51f124SMoriah Waterland * applied to each package object that inserting them one-by-one doesn't cost 384*5c51f124SMoriah Waterland * that much. 385*5c51f124SMoriah Waterland */ 386*5c51f124SMoriah Waterland static int 387*5c51f124SMoriah Waterland sortentry(int index) 388*5c51f124SMoriah Waterland { 389*5c51f124SMoriah Waterland struct cfextra *ext; 390*5c51f124SMoriah Waterland struct cfent *ept, *ept_i; 391*5c51f124SMoriah Waterland static int last = 0; 392*5c51f124SMoriah Waterland int i, n, j; 393*5c51f124SMoriah Waterland int upper, lower; 394*5c51f124SMoriah Waterland 395*5c51f124SMoriah Waterland if (index == 0) 396*5c51f124SMoriah Waterland return (0); 397*5c51f124SMoriah Waterland else if (index < 0) { 398*5c51f124SMoriah Waterland last = 0; 399*5c51f124SMoriah Waterland return (0); 400*5c51f124SMoriah Waterland } 401*5c51f124SMoriah Waterland 402*5c51f124SMoriah Waterland /* 403*5c51f124SMoriah Waterland * Based on the index, this is the package object we're going to 404*5c51f124SMoriah Waterland * review. It may stay where it is or it may be repositioned in the 405*5c51f124SMoriah Waterland * array. 406*5c51f124SMoriah Waterland */ 407*5c51f124SMoriah Waterland ext = extlist[index]; 408*5c51f124SMoriah Waterland ept = &(ext->cf_ent); 409*5c51f124SMoriah Waterland 410*5c51f124SMoriah Waterland /* quick comparison optimization for pre-sorted arrays */ 411*5c51f124SMoriah Waterland if (strcmp(ept->path, extlist[index-1]->cf_ent.path) > 0) { 412*5c51f124SMoriah Waterland /* do nothing */ 413*5c51f124SMoriah Waterland last = index-1; 414*5c51f124SMoriah Waterland return (0); 415*5c51f124SMoriah Waterland } 416*5c51f124SMoriah Waterland 417*5c51f124SMoriah Waterland lower = 0; /* lower bound of the unsorted elements */ 418*5c51f124SMoriah Waterland upper = index; /* upper bound */ 419*5c51f124SMoriah Waterland i = last; 420*5c51f124SMoriah Waterland do { 421*5c51f124SMoriah Waterland /* 422*5c51f124SMoriah Waterland * NOTE: This does a binary sort on path. There are lots of 423*5c51f124SMoriah Waterland * other worthy items in the array, but path is the key into 424*5c51f124SMoriah Waterland * the package database. 425*5c51f124SMoriah Waterland */ 426*5c51f124SMoriah Waterland ept_i = &(extlist[i]->cf_ent); 427*5c51f124SMoriah Waterland 428*5c51f124SMoriah Waterland n = strcmp(ept->path, ept_i->path); 429*5c51f124SMoriah Waterland if (n == 0) { 430*5c51f124SMoriah Waterland if (!ckdup(ept, ept_i)) { 431*5c51f124SMoriah Waterland /* 432*5c51f124SMoriah Waterland * If the array was seeded then there are 433*5c51f124SMoriah Waterland * bound to be occasional duplicates. 434*5c51f124SMoriah Waterland * Otherwise, duplicates are definitely a 435*5c51f124SMoriah Waterland * sign of major damage. 436*5c51f124SMoriah Waterland */ 437*5c51f124SMoriah Waterland if (array_preloaded) { 438*5c51f124SMoriah Waterland if (!dup_merg(ext, extlist[i])) { 439*5c51f124SMoriah Waterland progerr(gettext(ERR_DUPPATH), 440*5c51f124SMoriah Waterland ept->path); 441*5c51f124SMoriah Waterland errflg++; 442*5c51f124SMoriah Waterland } 443*5c51f124SMoriah Waterland } else { 444*5c51f124SMoriah Waterland progerr(gettext(ERR_DUPPATH), 445*5c51f124SMoriah Waterland ept->path); 446*5c51f124SMoriah Waterland errflg++; 447*5c51f124SMoriah Waterland } 448*5c51f124SMoriah Waterland } 449*5c51f124SMoriah Waterland /* remove the entry at index */ 450*5c51f124SMoriah Waterland (void) ar_delete(xspace, index); 451*5c51f124SMoriah Waterland 452*5c51f124SMoriah Waterland eptnum--; 453*5c51f124SMoriah Waterland return (1); /* Use this index again. */ 454*5c51f124SMoriah Waterland } else if (n < 0) { 455*5c51f124SMoriah Waterland /* 456*5c51f124SMoriah Waterland * The path of interest is smaller than the path 457*5c51f124SMoriah Waterland * under test. Move down array using the method of 458*5c51f124SMoriah Waterland * division 459*5c51f124SMoriah Waterland */ 460*5c51f124SMoriah Waterland upper = i; 461*5c51f124SMoriah Waterland i = lower + (upper-lower)/2; 462*5c51f124SMoriah Waterland } else { 463*5c51f124SMoriah Waterland /* Move up array */ 464*5c51f124SMoriah Waterland lower = i+1; 465*5c51f124SMoriah Waterland i = upper - (upper-lower)/2 - 1; 466*5c51f124SMoriah Waterland } 467*5c51f124SMoriah Waterland } while (upper != lower); 468*5c51f124SMoriah Waterland last = i = upper; 469*5c51f124SMoriah Waterland 470*5c51f124SMoriah Waterland /* expand to insert at i */ 471*5c51f124SMoriah Waterland for (j = index; j > i; j--) 472*5c51f124SMoriah Waterland extlist[j] = extlist[j-1]; 473*5c51f124SMoriah Waterland 474*5c51f124SMoriah Waterland extlist[i] = ext; 475*5c51f124SMoriah Waterland 476*5c51f124SMoriah Waterland return (0); 477*5c51f124SMoriah Waterland } 478*5c51f124SMoriah Waterland 479*5c51f124SMoriah Waterland /* Return the number of blocks required by the package object provided. */ 480*5c51f124SMoriah Waterland static fsblkcnt_t 481*5c51f124SMoriah Waterland nblks(short fsys_entry, struct cfextra *ext) 482*5c51f124SMoriah Waterland { 483*5c51f124SMoriah Waterland fsblkcnt_t blk; 484*5c51f124SMoriah Waterland ulong_t block_size; 485*5c51f124SMoriah Waterland ulong_t frag_size; 486*5c51f124SMoriah Waterland 487*5c51f124SMoriah Waterland block_size = (ulong_t)get_blk_size_n(fsys_entry); 488*5c51f124SMoriah Waterland frag_size = (ulong_t)get_frag_size_n(fsys_entry); 489*5c51f124SMoriah Waterland 490*5c51f124SMoriah Waterland if (strchr("dxs", ext->cf_ent.ftype)) 491*5c51f124SMoriah Waterland blk = 492*5c51f124SMoriah Waterland nblk(block_size, block_size, frag_size); 493*5c51f124SMoriah Waterland else if (ext->cf_ent.cinfo.size != BADCONT) 494*5c51f124SMoriah Waterland blk = nblk(ext->cf_ent.cinfo.size, block_size, 495*5c51f124SMoriah Waterland frag_size); 496*5c51f124SMoriah Waterland else 497*5c51f124SMoriah Waterland blk = 0; 498*5c51f124SMoriah Waterland 499*5c51f124SMoriah Waterland return (blk); 500*5c51f124SMoriah Waterland } 501*5c51f124SMoriah Waterland 502*5c51f124SMoriah Waterland /* Remove ext1 from the filesystem size calculations and add ext2. */ 503*5c51f124SMoriah Waterland static void 504*5c51f124SMoriah Waterland size_xchng(struct cfextra *ext1, struct cfextra *ext2) 505*5c51f124SMoriah Waterland { 506*5c51f124SMoriah Waterland fsblkcnt_t bused; 507*5c51f124SMoriah Waterland ulong_t block_size; 508*5c51f124SMoriah Waterland ulong_t frag_size; 509*5c51f124SMoriah Waterland fsblkcnt_t blks1, blks2; 510*5c51f124SMoriah Waterland short fsys_entry; 511*5c51f124SMoriah Waterland 512*5c51f124SMoriah Waterland /* 513*5c51f124SMoriah Waterland * Since these are on the same filesystem, either one will yield the 514*5c51f124SMoriah Waterland * correct block and fragment size. 515*5c51f124SMoriah Waterland */ 516*5c51f124SMoriah Waterland fsys_entry = ext1->fsys_base; 517*5c51f124SMoriah Waterland block_size = (ulong_t)get_blk_size_n(fsys_entry); 518*5c51f124SMoriah Waterland frag_size = (ulong_t)get_frag_size_n(fsys_entry); 519*5c51f124SMoriah Waterland 520*5c51f124SMoriah Waterland blks1 = nblk(ext1->cf_ent.cinfo.size, block_size, frag_size); 521*5c51f124SMoriah Waterland blks2 = nblk(ext2->cf_ent.cinfo.size, block_size, frag_size); 522*5c51f124SMoriah Waterland 523*5c51f124SMoriah Waterland if (blks1 != blks2) { 524*5c51f124SMoriah Waterland /* First, lose the old size, then add the new size. */ 525*5c51f124SMoriah Waterland bused = get_blk_used_n(fsys_entry); 526*5c51f124SMoriah Waterland bused -= nblks(fsys_entry, ext1); 527*5c51f124SMoriah Waterland bused += nblks(fsys_entry, ext2); 528*5c51f124SMoriah Waterland 529*5c51f124SMoriah Waterland set_blk_used_n(fsys_entry, bused); 530*5c51f124SMoriah Waterland } 531*5c51f124SMoriah Waterland } 532*5c51f124SMoriah Waterland 533*5c51f124SMoriah Waterland /* 534*5c51f124SMoriah Waterland * This function merges duplicate non-directory entries resulting from a 535*5c51f124SMoriah Waterland * dryrun or other procedure which preloads the extlist. It uses an odd 536*5c51f124SMoriah Waterland * heuristic to determine which package object is newest: only package 537*5c51f124SMoriah Waterland * objects from the dryrun file will have pinfo pointers. Therefore, the 538*5c51f124SMoriah Waterland * object with a pinfo pointer is from the dryrun file and it will be 539*5c51f124SMoriah Waterland * overwritten by the object being installed by this package. 540*5c51f124SMoriah Waterland * 541*5c51f124SMoriah Waterland * Assumptions: 542*5c51f124SMoriah Waterland * 1. The newer object will be overwriting the older object. 543*5c51f124SMoriah Waterland * 2. The two objects are close enough to the same size that 544*5c51f124SMoriah Waterland * the sizing is still OK. 545*5c51f124SMoriah Waterland * 546*5c51f124SMoriah Waterland * The calling routine will overwrite ept1, so this must return ept2 with 547*5c51f124SMoriah Waterland * the correct data to keep. There being only one logical outcome of a 548*5c51f124SMoriah Waterland * failure, this returns 1 for OK and 0 for FAIL. 549*5c51f124SMoriah Waterland */ 550*5c51f124SMoriah Waterland static int 551*5c51f124SMoriah Waterland dup_merg(struct cfextra *ext1, struct cfextra *ext2) 552*5c51f124SMoriah Waterland { 553*5c51f124SMoriah Waterland struct cfent *ept1, *ept2; 554*5c51f124SMoriah Waterland 555*5c51f124SMoriah Waterland ept1 = &(ext1->cf_ent); 556*5c51f124SMoriah Waterland ept2 = &(ext2->cf_ent); 557*5c51f124SMoriah Waterland 558*5c51f124SMoriah Waterland if (strchr("?dx", ept1->ftype)) 559*5c51f124SMoriah Waterland return (0); 560*5c51f124SMoriah Waterland 561*5c51f124SMoriah Waterland if (strchr("?dx", ept2->ftype)) 562*5c51f124SMoriah Waterland return (0); 563*5c51f124SMoriah Waterland 564*5c51f124SMoriah Waterland /* First, which is the eldest? */ 565*5c51f124SMoriah Waterland if (ext2->mstat.preloaded) { 566*5c51f124SMoriah Waterland /* 567*5c51f124SMoriah Waterland * While ept2 has the correct pinfo list (it was preloaded into 568*5c51f124SMoriah Waterland * the array before the pkgmap was read), ept1 has everything 569*5c51f124SMoriah Waterland * else. Here we copy the guts of ept1 into ept2. 570*5c51f124SMoriah Waterland * 571*5c51f124SMoriah Waterland * Start by grabbing the pointers to the ext2 items that we 572*5c51f124SMoriah Waterland * need to either restore or free. 573*5c51f124SMoriah Waterland */ 574*5c51f124SMoriah Waterland /* to free() */ 575*5c51f124SMoriah Waterland char *path = ept2->path; 576*5c51f124SMoriah Waterland char *local = ept2->ainfo.local; 577*5c51f124SMoriah Waterland 578*5c51f124SMoriah Waterland /* to preserve */ 579*5c51f124SMoriah Waterland short npkgs = ept2->npkgs; 580*5c51f124SMoriah Waterland struct pinfo *pinfo = ept2->pinfo; 581*5c51f124SMoriah Waterland 582*5c51f124SMoriah Waterland /* Copy everything from the new entry to the old */ 583*5c51f124SMoriah Waterland (void) memcpy(ept2, ept1, sizeof (struct cfent)); 584*5c51f124SMoriah Waterland 585*5c51f124SMoriah Waterland /* Now restore the original stuff.. */ 586*5c51f124SMoriah Waterland ept2->path = path; 587*5c51f124SMoriah Waterland ept2->ainfo.local = local; 588*5c51f124SMoriah Waterland ept2->npkgs = npkgs; 589*5c51f124SMoriah Waterland ept2->pinfo = pinfo; 590*5c51f124SMoriah Waterland 591*5c51f124SMoriah Waterland size_xchng(ext2, ext1); 592*5c51f124SMoriah Waterland } else if (ext1->mstat.preloaded) { 593*5c51f124SMoriah Waterland /* 594*5c51f124SMoriah Waterland * ept2 is already the one we will keep. All we have to do is 595*5c51f124SMoriah Waterland * copy over the pinfo pointer. 596*5c51f124SMoriah Waterland */ 597*5c51f124SMoriah Waterland ept2->pinfo = ept1->pinfo; 598*5c51f124SMoriah Waterland size_xchng(ext1, ext2); 599*5c51f124SMoriah Waterland } else 600*5c51f124SMoriah Waterland return (0); 601*5c51f124SMoriah Waterland 602*5c51f124SMoriah Waterland return (1); 603*5c51f124SMoriah Waterland } 604*5c51f124SMoriah Waterland 605*5c51f124SMoriah Waterland /* 606*5c51f124SMoriah Waterland * Check duplicate entries in the package object list. If it's a directory, 607*5c51f124SMoriah Waterland * this just merges them, if not, it returns a 0 to force further processing. 608*5c51f124SMoriah Waterland */ 609*5c51f124SMoriah Waterland static int 610*5c51f124SMoriah Waterland ckdup(struct cfent *ept1, struct cfent *ept2) 611*5c51f124SMoriah Waterland { 612*5c51f124SMoriah Waterland /* ept2 will be modified to contain "merged" entries */ 613*5c51f124SMoriah Waterland 614*5c51f124SMoriah Waterland if (!strchr("?dx", ept1->ftype)) 615*5c51f124SMoriah Waterland return (0); 616*5c51f124SMoriah Waterland 617*5c51f124SMoriah Waterland if (!strchr("?dx", ept2->ftype)) 618*5c51f124SMoriah Waterland return (0); 619*5c51f124SMoriah Waterland 620*5c51f124SMoriah Waterland if (ept2->ainfo.mode == BADMODE) 621*5c51f124SMoriah Waterland ept2->ainfo.mode = ept1->ainfo.mode; 622*5c51f124SMoriah Waterland if ((ept1->ainfo.mode != ept2->ainfo.mode) && 623*5c51f124SMoriah Waterland (ept1->ainfo.mode != BADMODE)) 624*5c51f124SMoriah Waterland return (0); 625*5c51f124SMoriah Waterland 626*5c51f124SMoriah Waterland if (strcmp(ept2->ainfo.owner, "?") == 0) 627*5c51f124SMoriah Waterland (void) strlcpy(ept2->ainfo.owner, ept1->ainfo.owner, 628*5c51f124SMoriah Waterland sizeof (ept2->ainfo.owner)); 629*5c51f124SMoriah Waterland if (strcmp(ept1->ainfo.owner, ept2->ainfo.owner) && 630*5c51f124SMoriah Waterland strcmp(ept1->ainfo.owner, "?")) 631*5c51f124SMoriah Waterland return (0); 632*5c51f124SMoriah Waterland 633*5c51f124SMoriah Waterland if (strcmp(ept2->ainfo.group, "?") == 0) 634*5c51f124SMoriah Waterland (void) strlcpy(ept2->ainfo.group, ept1->ainfo.group, 635*5c51f124SMoriah Waterland sizeof (ept2->ainfo.group)); 636*5c51f124SMoriah Waterland if (strcmp(ept1->ainfo.group, ept2->ainfo.group) && 637*5c51f124SMoriah Waterland strcmp(ept1->ainfo.group, "?")) 638*5c51f124SMoriah Waterland return (0); 639*5c51f124SMoriah Waterland 640*5c51f124SMoriah Waterland if (ept1->pinfo) { 641*5c51f124SMoriah Waterland ept2->npkgs = ept1->npkgs; 642*5c51f124SMoriah Waterland ept2->pinfo = ept1->pinfo; 643*5c51f124SMoriah Waterland } 644*5c51f124SMoriah Waterland 645*5c51f124SMoriah Waterland return (1); 646*5c51f124SMoriah Waterland } 647*5c51f124SMoriah Waterland 648*5c51f124SMoriah Waterland /* 649*5c51f124SMoriah Waterland * Replace the old package database entry with the new one preserving the 650*5c51f124SMoriah Waterland * data which remains constant across the replacement. 651*5c51f124SMoriah Waterland * copied directly: 652*5c51f124SMoriah Waterland * ftype, pkg_class 653*5c51f124SMoriah Waterland * 654*5c51f124SMoriah Waterland * preserved from old: 655*5c51f124SMoriah Waterland * path, npkgs, pinfo 656*5c51f124SMoriah Waterland */ 657*5c51f124SMoriah Waterland void 658*5c51f124SMoriah Waterland repl_cfent(struct cfent *new, struct cfent *old) 659*5c51f124SMoriah Waterland { 660*5c51f124SMoriah Waterland char *path = old->path; 661*5c51f124SMoriah Waterland short npkgs = old->npkgs; 662*5c51f124SMoriah Waterland struct pinfo *pinfo = old->pinfo; 663*5c51f124SMoriah Waterland 664*5c51f124SMoriah Waterland /* Copy everything from the new entry over */ 665*5c51f124SMoriah Waterland (void) memcpy(old, new, sizeof (struct cfent)); 666*5c51f124SMoriah Waterland 667*5c51f124SMoriah Waterland if (strchr("sl", new->ftype) == NULL) 668*5c51f124SMoriah Waterland old->ainfo.local = NULL; 669*5c51f124SMoriah Waterland 670*5c51f124SMoriah Waterland old->path = path; 671*5c51f124SMoriah Waterland old->npkgs = npkgs; 672*5c51f124SMoriah Waterland old->pinfo = pinfo; 673*5c51f124SMoriah Waterland 674*5c51f124SMoriah Waterland old->volno = 0; 675*5c51f124SMoriah Waterland } 676*5c51f124SMoriah Waterland 677*5c51f124SMoriah Waterland /* 678*5c51f124SMoriah Waterland * Copy critical portions of cf_ent (from the package database) and el_ent 679*5c51f124SMoriah Waterland * (constructed from the pkgmap) into a merged cfent structure, tp. Then copy 680*5c51f124SMoriah Waterland * that to the el_ent structure. The approach we take here is to copy over 681*5c51f124SMoriah Waterland * everything from the package database entry, condition the paths based upon 682*5c51f124SMoriah Waterland * the currently installed path and then insert the following entries from 683*5c51f124SMoriah Waterland * the new structure : 684*5c51f124SMoriah Waterland * cfent.volno 685*5c51f124SMoriah Waterland * pkg_class 686*5c51f124SMoriah Waterland * pkg_class_idx 687*5c51f124SMoriah Waterland * 688*5c51f124SMoriah Waterland * The pinfo list is then copied from the cfent list. While 689*5c51f124SMoriah Waterland * fsys_value is also copied over, it hasn't been set yet. This function 690*5c51f124SMoriah Waterland * copies over whatever the default value is from the new structure. 691*5c51f124SMoriah Waterland * 692*5c51f124SMoriah Waterland * The copied entry is returned in the el_ent argument and the function 693*5c51f124SMoriah Waterland * value is 1 on success, 0 on failure. There is no recovery plan for 694*5c51f124SMoriah Waterland * failure. 695*5c51f124SMoriah Waterland */ 696*5c51f124SMoriah Waterland int 697*5c51f124SMoriah Waterland cp_cfent(struct cfent *cf_ent, struct cfextra *el_ent) 698*5c51f124SMoriah Waterland { 699*5c51f124SMoriah Waterland struct cfextra *tp; 700*5c51f124SMoriah Waterland 701*5c51f124SMoriah Waterland /* Allocate space for cfent copy */ 702*5c51f124SMoriah Waterland if ((tp = (struct cfextra *)calloc(1, 703*5c51f124SMoriah Waterland sizeof (struct cfextra))) == NULL) { 704*5c51f124SMoriah Waterland progerr(gettext("cp_cfent: memory allocation error")); 705*5c51f124SMoriah Waterland return (0); 706*5c51f124SMoriah Waterland } 707*5c51f124SMoriah Waterland 708*5c51f124SMoriah Waterland /* Copy everything from the package database over */ 709*5c51f124SMoriah Waterland (void) memcpy(&(tp->cf_ent), cf_ent, sizeof (struct cfent)); 710*5c51f124SMoriah Waterland 711*5c51f124SMoriah Waterland /* Now overlay new items from the pkgmap */ 712*5c51f124SMoriah Waterland tp->fsys_value = el_ent->fsys_value; 713*5c51f124SMoriah Waterland tp->cf_ent.volno = el_ent->cf_ent.volno; 714*5c51f124SMoriah Waterland (void) strlcpy(tp->cf_ent.pkg_class, el_ent->cf_ent.pkg_class, 715*5c51f124SMoriah Waterland sizeof (tp->cf_ent.pkg_class)); 716*5c51f124SMoriah Waterland tp->cf_ent.pkg_class_idx = el_ent->cf_ent.pkg_class_idx; 717*5c51f124SMoriah Waterland tp->cf_ent.pinfo = cf_ent->pinfo; 718*5c51f124SMoriah Waterland 719*5c51f124SMoriah Waterland /* 720*5c51f124SMoriah Waterland * The paths are identical, so we get them from the new entry. These 721*5c51f124SMoriah Waterland * are pointing to a malloc'd section of memory containing a string 722*5c51f124SMoriah Waterland * that we aren't moving in this operation, so everybody points to 723*5c51f124SMoriah Waterland * the same thing during these transfers. 724*5c51f124SMoriah Waterland */ 725*5c51f124SMoriah Waterland tp->cf_ent.path = el_ent->client_path; 726*5c51f124SMoriah Waterland tp->server_path = el_ent->server_path; 727*5c51f124SMoriah Waterland tp->client_path = el_ent->client_path; 728*5c51f124SMoriah Waterland tp->map_path = el_ent->map_path; 729*5c51f124SMoriah Waterland 730*5c51f124SMoriah Waterland /* 731*5c51f124SMoriah Waterland * Since instvol() expects to work with the *original* mstat data, 732*5c51f124SMoriah Waterland * mstat is just copied here. NOTE: mstat looks like a structure, but 733*5c51f124SMoriah Waterland * it's really a short bit array. 734*5c51f124SMoriah Waterland */ 735*5c51f124SMoriah Waterland tp->mstat = el_ent->mstat; 736*5c51f124SMoriah Waterland 737*5c51f124SMoriah Waterland /* Copy everything from the temporary structure to the new entry */ 738*5c51f124SMoriah Waterland (void) memcpy(el_ent, tp, sizeof (struct cfextra)); 739*5c51f124SMoriah Waterland free(tp); 740*5c51f124SMoriah Waterland 741*5c51f124SMoriah Waterland return (1); 742*5c51f124SMoriah Waterland } 743