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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*5c51f124SMoriah Waterland /* All Rights Reserved */ 29*5c51f124SMoriah Waterland 30*5c51f124SMoriah Waterland 31*5c51f124SMoriah Waterland #include <stdio.h> 32*5c51f124SMoriah Waterland #include <errno.h> 33*5c51f124SMoriah Waterland #include <string.h> 34*5c51f124SMoriah Waterland #include <limits.h> 35*5c51f124SMoriah Waterland #include <stdlib.h> 36*5c51f124SMoriah Waterland #include <unistd.h> 37*5c51f124SMoriah Waterland #include <sys/types.h> 38*5c51f124SMoriah Waterland #include <sys/param.h> 39*5c51f124SMoriah Waterland #include <pkgdev.h> 40*5c51f124SMoriah Waterland #include <pkgstrct.h> 41*5c51f124SMoriah Waterland #include <locale.h> 42*5c51f124SMoriah Waterland #include <libintl.h> 43*5c51f124SMoriah Waterland #include <pkglib.h> 44*5c51f124SMoriah Waterland #include <libadm.h> 45*5c51f124SMoriah Waterland #include <libinst.h> 46*5c51f124SMoriah Waterland 47*5c51f124SMoriah Waterland extern struct pkgdev pkgdev; 48*5c51f124SMoriah Waterland 49*5c51f124SMoriah Waterland #define MALSIZ 500 50*5c51f124SMoriah Waterland #define EFACTOR 128ULL /* typical size of a single entry in a pkgmap file */ 51*5c51f124SMoriah Waterland 52*5c51f124SMoriah Waterland #define WRN_LIMIT "WARNING: -l limit (%llu blocks) exceeds device " \ 53*5c51f124SMoriah Waterland "capacity (%llu blocks)" 54*5c51f124SMoriah Waterland #define ERR_MEMORY "memory allocation failure, errno=%d" 55*5c51f124SMoriah Waterland #define ERR_TOOBIG "%s (%llu blocks) does not fit on a volume" 56*5c51f124SMoriah Waterland #define ERR_INFOFIRST "information file <%s> must appear on first part" 57*5c51f124SMoriah Waterland #define ERR_INFOSPACE "all install files must appear on first part" 58*5c51f124SMoriah Waterland #define ERR_VOLBLKS "Objects selected for part %d require %llu blocks, " \ 59*5c51f124SMoriah Waterland "limit=%llu." 60*5c51f124SMoriah Waterland #define ERR_VOLFILES "Objects selected for part %d require %llu files, " \ 61*5c51f124SMoriah Waterland "limit=%llu." 62*5c51f124SMoriah Waterland #define ERR_FREE "package does not fit space currently available in <%s>" 63*5c51f124SMoriah Waterland 64*5c51f124SMoriah Waterland struct data { 65*5c51f124SMoriah Waterland fsblkcnt_t blks; 66*5c51f124SMoriah Waterland struct cfent *ept; 67*5c51f124SMoriah Waterland }; 68*5c51f124SMoriah Waterland 69*5c51f124SMoriah Waterland struct class_type { 70*5c51f124SMoriah Waterland char *name; 71*5c51f124SMoriah Waterland int first; 72*5c51f124SMoriah Waterland int last; 73*5c51f124SMoriah Waterland }; 74*5c51f124SMoriah Waterland 75*5c51f124SMoriah Waterland static fsblkcnt_t btotal; /* blocks stored on current part */ 76*5c51f124SMoriah Waterland static fsblkcnt_t bmax; /* maximum number of blocks on any part */ 77*5c51f124SMoriah Waterland 78*5c51f124SMoriah Waterland static fsfilcnt_t ftotal; /* files stored on current part */ 79*5c51f124SMoriah Waterland static fsfilcnt_t fmax; /* maximum number of files on any part */ 80*5c51f124SMoriah Waterland static fsblkcnt_t bpkginfo; /* blocks used by pkginfo file */ 81*5c51f124SMoriah Waterland static char **dirlist; 82*5c51f124SMoriah Waterland static short volno; /* current part */ 83*5c51f124SMoriah Waterland static int nparts = -1; /* total number of parts */ 84*5c51f124SMoriah Waterland static int nclass; 85*5c51f124SMoriah Waterland static fsblkcnt_t DIRSIZE; 86*5c51f124SMoriah Waterland static struct class_type *cl; 87*5c51f124SMoriah Waterland 88*5c51f124SMoriah Waterland static int nodecount(char *path); 89*5c51f124SMoriah Waterland static int store(struct data **, unsigned int, char *, fsblkcnt_t, 90*5c51f124SMoriah Waterland fsblkcnt_t); 91*5c51f124SMoriah Waterland static void addclass(char *aclass, int vol); 92*5c51f124SMoriah Waterland static void allocnode(char *path); 93*5c51f124SMoriah Waterland static void newvolume(struct data **, unsigned int, fsblkcnt_t limit, 94*5c51f124SMoriah Waterland fsblkcnt_t); 95*5c51f124SMoriah Waterland static void sortsize(struct data *f, struct data **sf, unsigned int eptnum); 96*5c51f124SMoriah Waterland 97*5c51f124SMoriah Waterland int 98*5c51f124SMoriah Waterland splpkgmap(struct cfent **eptlist, unsigned int eptnum, char *order[], 99*5c51f124SMoriah Waterland ulong_t bsize, ulong_t frsize, fsblkcnt_t *plimit, fsfilcnt_t *pilimit, 100*5c51f124SMoriah Waterland fsblkcnt_t *pllimit) 101*5c51f124SMoriah Waterland { 102*5c51f124SMoriah Waterland struct data *f, **sf; 103*5c51f124SMoriah Waterland struct cfent *ept; 104*5c51f124SMoriah Waterland register int i, j; 105*5c51f124SMoriah Waterland int new_vol_set; 106*5c51f124SMoriah Waterland short new_vol; 107*5c51f124SMoriah Waterland int flag, errflg; 108*5c51f124SMoriah Waterland fsblkcnt_t total; 109*5c51f124SMoriah Waterland fsblkcnt_t btemp; 110*5c51f124SMoriah Waterland fsfilcnt_t ftemp; 111*5c51f124SMoriah Waterland 112*5c51f124SMoriah Waterland f = (struct data *)calloc(eptnum, sizeof (struct data)); 113*5c51f124SMoriah Waterland if (f == NULL) { 114*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 115*5c51f124SMoriah Waterland quit(99); 116*5c51f124SMoriah Waterland } 117*5c51f124SMoriah Waterland 118*5c51f124SMoriah Waterland sf = (struct data **)calloc(eptnum, sizeof (struct data *)); 119*5c51f124SMoriah Waterland if (sf == NULL) { 120*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 121*5c51f124SMoriah Waterland quit(99); 122*5c51f124SMoriah Waterland } 123*5c51f124SMoriah Waterland 124*5c51f124SMoriah Waterland nclass = 0; 125*5c51f124SMoriah Waterland cl = (struct class_type *)calloc(MALSIZ, sizeof (struct class_type)); 126*5c51f124SMoriah Waterland if (cl == NULL) { 127*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 128*5c51f124SMoriah Waterland quit(99); 129*5c51f124SMoriah Waterland } 130*5c51f124SMoriah Waterland 131*5c51f124SMoriah Waterland errflg = 0; 132*5c51f124SMoriah Waterland 133*5c51f124SMoriah Waterland /* 134*5c51f124SMoriah Waterland * The next bit of code checks to see if, when creating a package 135*5c51f124SMoriah Waterland * on a directory, there are enough free blocks and inodes before 136*5c51f124SMoriah Waterland * continuing. 137*5c51f124SMoriah Waterland */ 138*5c51f124SMoriah Waterland total = 0; 139*5c51f124SMoriah Waterland /* 140*5c51f124SMoriah Waterland * DIRSIZE takes up 1 logical block, iff we have no frags, else 141*5c51f124SMoriah Waterland * it just takes a frag 142*5c51f124SMoriah Waterland */ 143*5c51f124SMoriah Waterland DIRSIZE = ((fsblkcnt_t)frsize > 0) ? 144*5c51f124SMoriah Waterland howmany(frsize, DEV_BSIZE) : 145*5c51f124SMoriah Waterland howmany(bsize, DEV_BSIZE); 146*5c51f124SMoriah Waterland 147*5c51f124SMoriah Waterland if (!pkgdev.mount) { 148*5c51f124SMoriah Waterland allocnode(NULL); 149*5c51f124SMoriah Waterland /* 150*5c51f124SMoriah Waterland * If we appear to have a valid value for free inodes 151*5c51f124SMoriah Waterland * and there's not enough for the package contents, 152*5c51f124SMoriah Waterland * then exit 153*5c51f124SMoriah Waterland */ 154*5c51f124SMoriah Waterland if ((*pilimit > 0) && (eptnum+1 > *pilimit)) { 155*5c51f124SMoriah Waterland progerr(gettext(ERR_FREE), pkgdev.dirname); 156*5c51f124SMoriah Waterland quit(1); 157*5c51f124SMoriah Waterland } 158*5c51f124SMoriah Waterland for (i = 0; i < eptnum; i++) { 159*5c51f124SMoriah Waterland if (strchr("dxslcbp", eptlist[i]->ftype)) 160*5c51f124SMoriah Waterland continue; 161*5c51f124SMoriah Waterland else { 162*5c51f124SMoriah Waterland total += 163*5c51f124SMoriah Waterland (nodecount(eptlist[i]->path) * DIRSIZE); 164*5c51f124SMoriah Waterland total += 165*5c51f124SMoriah Waterland nblk(eptlist[i]->cinfo.size, bsize, frsize); 166*5c51f124SMoriah Waterland if (total > *plimit) { 167*5c51f124SMoriah Waterland progerr(gettext(ERR_FREE), 168*5c51f124SMoriah Waterland pkgdev.dirname); 169*5c51f124SMoriah Waterland quit(1); 170*5c51f124SMoriah Waterland } 171*5c51f124SMoriah Waterland allocnode(eptlist[i]->path); 172*5c51f124SMoriah Waterland } 173*5c51f124SMoriah Waterland } 174*5c51f124SMoriah Waterland } 175*5c51f124SMoriah Waterland /* 176*5c51f124SMoriah Waterland * if there is a value in pllimit (-l specified limit), use that for 177*5c51f124SMoriah Waterland * the limit from now on. 178*5c51f124SMoriah Waterland */ 179*5c51f124SMoriah Waterland 180*5c51f124SMoriah Waterland if (*pllimit != 0) { 181*5c51f124SMoriah Waterland if (pkgdev.mount && *pllimit > *plimit) 182*5c51f124SMoriah Waterland logerr(gettext(WRN_LIMIT), *pllimit, *plimit); 183*5c51f124SMoriah Waterland *plimit = *pllimit; 184*5c51f124SMoriah Waterland } 185*5c51f124SMoriah Waterland /* 186*5c51f124SMoriah Waterland * calculate number of physical blocks used by each object 187*5c51f124SMoriah Waterland */ 188*5c51f124SMoriah Waterland for (i = 0; i < eptnum; i++) { 189*5c51f124SMoriah Waterland f[i].ept = ept = eptlist[i]; 190*5c51f124SMoriah Waterland if (ept->volno > nparts) 191*5c51f124SMoriah Waterland nparts = ept->volno; 192*5c51f124SMoriah Waterland addclass(ept->pkg_class, 0); 193*5c51f124SMoriah Waterland if (strchr("dxslcbp", ept->ftype)) 194*5c51f124SMoriah Waterland /* 195*5c51f124SMoriah Waterland * virtual object (no contents) 196*5c51f124SMoriah Waterland */ 197*5c51f124SMoriah Waterland f[i].blks = 0; 198*5c51f124SMoriah Waterland else 199*5c51f124SMoriah Waterland /* 200*5c51f124SMoriah Waterland * space consumers 201*5c51f124SMoriah Waterland * 202*5c51f124SMoriah Waterland * (directories are space consumers as well, but they 203*5c51f124SMoriah Waterland * get accounted for later). 204*5c51f124SMoriah Waterland * 205*5c51f124SMoriah Waterland */ 206*5c51f124SMoriah Waterland 207*5c51f124SMoriah Waterland f[i].blks = nblk(ept->cinfo.size, bsize, frsize); 208*5c51f124SMoriah Waterland 209*5c51f124SMoriah Waterland if (!bpkginfo && (strcmp(f[i].ept->path, "pkginfo") == 0)) 210*5c51f124SMoriah Waterland bpkginfo = f[i].blks; 211*5c51f124SMoriah Waterland } 212*5c51f124SMoriah Waterland 213*5c51f124SMoriah Waterland /* 214*5c51f124SMoriah Waterland * Make sure that items slated for a given 'part' do not exceed a single 215*5c51f124SMoriah Waterland * volume. 216*5c51f124SMoriah Waterland */ 217*5c51f124SMoriah Waterland for (i = 1; i <= nparts; i++) { 218*5c51f124SMoriah Waterland btemp = (bpkginfo + 2LL); 219*5c51f124SMoriah Waterland ftemp = 2LL; 220*5c51f124SMoriah Waterland if (i == 1) { 221*5c51f124SMoriah Waterland /* 222*5c51f124SMoriah Waterland * save room for install directory 223*5c51f124SMoriah Waterland */ 224*5c51f124SMoriah Waterland ftemp += 2; 225*5c51f124SMoriah Waterland btemp += nblk(eptnum * EFACTOR, bsize, frsize); 226*5c51f124SMoriah Waterland btemp += 2; 227*5c51f124SMoriah Waterland } 228*5c51f124SMoriah Waterland allocnode(NULL); 229*5c51f124SMoriah Waterland for (j = 0; j < eptnum; j++) { 230*5c51f124SMoriah Waterland if (i == 1 && f[j].ept->ftype == 'i' && 231*5c51f124SMoriah Waterland (strcmp(f[j].ept->path, "pkginfo") == 0 || 232*5c51f124SMoriah Waterland strcmp(f[j].ept->path, "pkgmap") == 0)) 233*5c51f124SMoriah Waterland continue; 234*5c51f124SMoriah Waterland if (f[j].ept->volno == i || 235*5c51f124SMoriah Waterland (f[j].ept->ftype == 'i' && i == 1)) { 236*5c51f124SMoriah Waterland ftemp += nodecount(f[j].ept->path); 237*5c51f124SMoriah Waterland btemp += f[j].blks; 238*5c51f124SMoriah Waterland allocnode(f[j].ept->path); 239*5c51f124SMoriah Waterland } 240*5c51f124SMoriah Waterland } 241*5c51f124SMoriah Waterland btemp += (ftemp * DIRSIZE); 242*5c51f124SMoriah Waterland if (btemp > *plimit) { 243*5c51f124SMoriah Waterland progerr(gettext(ERR_VOLBLKS), i, btemp, *plimit); 244*5c51f124SMoriah Waterland errflg++; 245*5c51f124SMoriah Waterland /* If we have a valid inode limit, ensure this part will fit */ 246*5c51f124SMoriah Waterland } else if ((*pilimit > 0) && (ftemp+1 > *pilimit)) { 247*5c51f124SMoriah Waterland progerr(gettext(ERR_VOLFILES), i, ftemp + 1, *pilimit); 248*5c51f124SMoriah Waterland errflg++; 249*5c51f124SMoriah Waterland } 250*5c51f124SMoriah Waterland } 251*5c51f124SMoriah Waterland if (errflg) 252*5c51f124SMoriah Waterland quit(1); 253*5c51f124SMoriah Waterland 254*5c51f124SMoriah Waterland /* 255*5c51f124SMoriah Waterland * "sf" - array sorted in decreasing file size order, based on "f". 256*5c51f124SMoriah Waterland */ 257*5c51f124SMoriah Waterland sortsize(f, sf, eptnum); 258*5c51f124SMoriah Waterland 259*5c51f124SMoriah Waterland /* 260*5c51f124SMoriah Waterland * initialize first volume 261*5c51f124SMoriah Waterland */ 262*5c51f124SMoriah Waterland newvolume(sf, eptnum, *plimit, *pilimit); 263*5c51f124SMoriah Waterland 264*5c51f124SMoriah Waterland /* 265*5c51f124SMoriah Waterland * reserve room on first volume for pkgmap 266*5c51f124SMoriah Waterland */ 267*5c51f124SMoriah Waterland btotal += nblk((fsblkcnt_t)(eptnum * EFACTOR), bsize, frsize); 268*5c51f124SMoriah Waterland ftotal++; 269*5c51f124SMoriah Waterland 270*5c51f124SMoriah Waterland 271*5c51f124SMoriah Waterland /* 272*5c51f124SMoriah Waterland * initialize directory info 273*5c51f124SMoriah Waterland */ 274*5c51f124SMoriah Waterland allocnode(NULL); 275*5c51f124SMoriah Waterland 276*5c51f124SMoriah Waterland /* 277*5c51f124SMoriah Waterland * place installation files on first volume! 278*5c51f124SMoriah Waterland */ 279*5c51f124SMoriah Waterland flag = 0; 280*5c51f124SMoriah Waterland for (j = 0; j < eptnum; ++j) { 281*5c51f124SMoriah Waterland if (f[j].ept->ftype != 'i') 282*5c51f124SMoriah Waterland continue; 283*5c51f124SMoriah Waterland else if (!flag++) { 284*5c51f124SMoriah Waterland /* 285*5c51f124SMoriah Waterland * save room for install directory 286*5c51f124SMoriah Waterland */ 287*5c51f124SMoriah Waterland ftotal++; 288*5c51f124SMoriah Waterland btotal += 2ULL; 289*5c51f124SMoriah Waterland } 290*5c51f124SMoriah Waterland if (!f[j].ept->volno) { 291*5c51f124SMoriah Waterland f[j].ept->volno = 1; 292*5c51f124SMoriah Waterland ftotal++; 293*5c51f124SMoriah Waterland btotal += f[j].blks; 294*5c51f124SMoriah Waterland } else if (f[j].ept->volno != 1) { 295*5c51f124SMoriah Waterland progerr(gettext(ERR_INFOFIRST), f[j].ept->path); 296*5c51f124SMoriah Waterland errflg++; 297*5c51f124SMoriah Waterland } 298*5c51f124SMoriah Waterland } 299*5c51f124SMoriah Waterland 300*5c51f124SMoriah Waterland if (errflg) 301*5c51f124SMoriah Waterland quit(1); 302*5c51f124SMoriah Waterland if (btotal > *plimit) { 303*5c51f124SMoriah Waterland progerr(gettext(ERR_INFOSPACE)); 304*5c51f124SMoriah Waterland quit(1); 305*5c51f124SMoriah Waterland } 306*5c51f124SMoriah Waterland 307*5c51f124SMoriah Waterland /* 308*5c51f124SMoriah Waterland * Make sure that any given file will fit on a single volume, this 309*5c51f124SMoriah Waterland * calculation has to take into account packaging overhead, otherwise 310*5c51f124SMoriah Waterland * the function store() will go into a severe recursive plunge. 311*5c51f124SMoriah Waterland */ 312*5c51f124SMoriah Waterland for (j = 0; j < eptnum; ++j) { 313*5c51f124SMoriah Waterland /* 314*5c51f124SMoriah Waterland * directory overhead. 315*5c51f124SMoriah Waterland */ 316*5c51f124SMoriah Waterland btemp = nodecount(f[j].ept->path) * DIRSIZE; 317*5c51f124SMoriah Waterland /* 318*5c51f124SMoriah Waterland * packaging overhead. 319*5c51f124SMoriah Waterland */ 320*5c51f124SMoriah Waterland btemp += (bpkginfo + 2L); /* from newvolume() */ 321*5c51f124SMoriah Waterland if ((f[j].blks + btemp) > *plimit) { 322*5c51f124SMoriah Waterland errflg++; 323*5c51f124SMoriah Waterland progerr(gettext(ERR_TOOBIG), f[j].ept->path, f[j].blks); 324*5c51f124SMoriah Waterland } 325*5c51f124SMoriah Waterland } 326*5c51f124SMoriah Waterland if (errflg) 327*5c51f124SMoriah Waterland quit(1); 328*5c51f124SMoriah Waterland 329*5c51f124SMoriah Waterland /* 330*5c51f124SMoriah Waterland * place classes listed on command line 331*5c51f124SMoriah Waterland */ 332*5c51f124SMoriah Waterland if (order) { 333*5c51f124SMoriah Waterland for (i = 0; order[i]; ++i) { 334*5c51f124SMoriah Waterland while (store(sf, eptnum, order[i], *plimit, *pilimit)) 335*5c51f124SMoriah Waterland /* stay in loop until store is complete */ 336*5c51f124SMoriah Waterland /* void */; 337*5c51f124SMoriah Waterland } 338*5c51f124SMoriah Waterland } 339*5c51f124SMoriah Waterland 340*5c51f124SMoriah Waterland while (store(sf, eptnum, (char *)0, *plimit, *pilimit)) 341*5c51f124SMoriah Waterland /* stay in loop until store is complete */ 342*5c51f124SMoriah Waterland /* void */; 343*5c51f124SMoriah Waterland 344*5c51f124SMoriah Waterland /* 345*5c51f124SMoriah Waterland * place all virtual objects, e.g. links and spec devices 346*5c51f124SMoriah Waterland */ 347*5c51f124SMoriah Waterland for (i = 0; i < nclass; ++i) { 348*5c51f124SMoriah Waterland /* 349*5c51f124SMoriah Waterland * if no objects were associated, attempt to 350*5c51f124SMoriah Waterland * distribute in order of class list 351*5c51f124SMoriah Waterland */ 352*5c51f124SMoriah Waterland if (cl[i].first == 0) 353*5c51f124SMoriah Waterland cl[i].last = cl[i].first = (i ? cl[i-1].last : 1); 354*5c51f124SMoriah Waterland for (j = 0; j < eptnum; j++) { 355*5c51f124SMoriah Waterland if ((f[j].ept->volno == 0) && 356*5c51f124SMoriah Waterland strcmp(f[j].ept->pkg_class, cl[i].name) == 0) { 357*5c51f124SMoriah Waterland if (strchr("sl", f[j].ept->ftype)) 358*5c51f124SMoriah Waterland f[j].ept->volno = cl[i].last; 359*5c51f124SMoriah Waterland else 360*5c51f124SMoriah Waterland f[j].ept->volno = cl[i].first; 361*5c51f124SMoriah Waterland } 362*5c51f124SMoriah Waterland } 363*5c51f124SMoriah Waterland } 364*5c51f124SMoriah Waterland 365*5c51f124SMoriah Waterland if (btotal) 366*5c51f124SMoriah Waterland newvolume(sf, eptnum, *plimit, *pilimit); 367*5c51f124SMoriah Waterland 368*5c51f124SMoriah Waterland if (nparts > (volno - 1)) { 369*5c51f124SMoriah Waterland new_vol = volno; 370*5c51f124SMoriah Waterland for (i = volno; i <= nparts; i++) { 371*5c51f124SMoriah Waterland new_vol_set = 0; 372*5c51f124SMoriah Waterland for (j = 0; j < eptnum; j++) { 373*5c51f124SMoriah Waterland if (f[j].ept->volno == i) { 374*5c51f124SMoriah Waterland f[j].ept->volno = new_vol; 375*5c51f124SMoriah Waterland new_vol_set = 1; 376*5c51f124SMoriah Waterland } 377*5c51f124SMoriah Waterland } 378*5c51f124SMoriah Waterland new_vol += new_vol_set; 379*5c51f124SMoriah Waterland } 380*5c51f124SMoriah Waterland nparts = new_vol - 1; 381*5c51f124SMoriah Waterland } else 382*5c51f124SMoriah Waterland nparts = volno - 1; 383*5c51f124SMoriah Waterland 384*5c51f124SMoriah Waterland *plimit = bmax; 385*5c51f124SMoriah Waterland *pilimit = fmax; 386*5c51f124SMoriah Waterland 387*5c51f124SMoriah Waterland /* 388*5c51f124SMoriah Waterland * free up dynamic space used by this module 389*5c51f124SMoriah Waterland */ 390*5c51f124SMoriah Waterland free(f); 391*5c51f124SMoriah Waterland free(sf); 392*5c51f124SMoriah Waterland for (i = 0; i < nclass; ++i) 393*5c51f124SMoriah Waterland free(cl[i].name); 394*5c51f124SMoriah Waterland free(cl); 395*5c51f124SMoriah Waterland for (i = 0; dirlist[i]; i++) 396*5c51f124SMoriah Waterland free(dirlist[i]); 397*5c51f124SMoriah Waterland free(dirlist); 398*5c51f124SMoriah Waterland 399*5c51f124SMoriah Waterland return (errflg ? -1 : nparts); 400*5c51f124SMoriah Waterland } 401*5c51f124SMoriah Waterland 402*5c51f124SMoriah Waterland static int 403*5c51f124SMoriah Waterland store(struct data **sf, unsigned int eptnum, char *aclass, fsblkcnt_t limit, 404*5c51f124SMoriah Waterland fsfilcnt_t ilimit) 405*5c51f124SMoriah Waterland { 406*5c51f124SMoriah Waterland int i, svnodes, choice, select; 407*5c51f124SMoriah Waterland long ftemp; 408*5c51f124SMoriah Waterland fsblkcnt_t btemp; 409*5c51f124SMoriah Waterland 410*5c51f124SMoriah Waterland select = 0; 411*5c51f124SMoriah Waterland choice = (-1); 412*5c51f124SMoriah Waterland for (i = 0; i < eptnum; ++i) { 413*5c51f124SMoriah Waterland if (sf[i]->ept->volno || strchr("sldxcbp", sf[i]->ept->ftype)) 414*5c51f124SMoriah Waterland continue; /* defer storage until class is selected */ 415*5c51f124SMoriah Waterland if (aclass && strcmp(aclass, sf[i]->ept->pkg_class)) 416*5c51f124SMoriah Waterland continue; 417*5c51f124SMoriah Waterland select++; /* we need to place at least one object */ 418*5c51f124SMoriah Waterland ftemp = nodecount(sf[i]->ept->path); 419*5c51f124SMoriah Waterland btemp = sf[i]->blks + (ftemp * DIRSIZE); 420*5c51f124SMoriah Waterland if (((limit == 0) || ((btotal + btemp) <= limit)) && 421*5c51f124SMoriah Waterland ((ilimit == 0) || ((ftotal + ftemp) < ilimit))) { 422*5c51f124SMoriah Waterland /* largest object which fits on this volume */ 423*5c51f124SMoriah Waterland choice = i; 424*5c51f124SMoriah Waterland svnodes = ftemp; 425*5c51f124SMoriah Waterland break; 426*5c51f124SMoriah Waterland } 427*5c51f124SMoriah Waterland } 428*5c51f124SMoriah Waterland if (!select) 429*5c51f124SMoriah Waterland return (0); /* no more to objects to place */ 430*5c51f124SMoriah Waterland 431*5c51f124SMoriah Waterland if (choice < 0) { 432*5c51f124SMoriah Waterland newvolume(sf, eptnum, limit, ilimit); 433*5c51f124SMoriah Waterland return (store(sf, eptnum, aclass, limit, ilimit)); 434*5c51f124SMoriah Waterland } 435*5c51f124SMoriah Waterland sf[choice]->ept->volno = (char)volno; 436*5c51f124SMoriah Waterland ftotal += svnodes + 1; 437*5c51f124SMoriah Waterland btotal += sf[choice]->blks + (svnodes * DIRSIZE); 438*5c51f124SMoriah Waterland allocnode(sf[i]->ept->path); 439*5c51f124SMoriah Waterland addclass(sf[choice]->ept->pkg_class, volno); 440*5c51f124SMoriah Waterland return (++choice); /* return non-zero if more work to do */ 441*5c51f124SMoriah Waterland } 442*5c51f124SMoriah Waterland 443*5c51f124SMoriah Waterland static void 444*5c51f124SMoriah Waterland allocnode(char *path) 445*5c51f124SMoriah Waterland { 446*5c51f124SMoriah Waterland register int i; 447*5c51f124SMoriah Waterland int found; 448*5c51f124SMoriah Waterland char *pt; 449*5c51f124SMoriah Waterland 450*5c51f124SMoriah Waterland if (path == NULL) { 451*5c51f124SMoriah Waterland if (dirlist) { 452*5c51f124SMoriah Waterland /* 453*5c51f124SMoriah Waterland * free everything 454*5c51f124SMoriah Waterland */ 455*5c51f124SMoriah Waterland for (i = 0; dirlist[i]; i++) 456*5c51f124SMoriah Waterland free(dirlist[i]); 457*5c51f124SMoriah Waterland free(dirlist); 458*5c51f124SMoriah Waterland } 459*5c51f124SMoriah Waterland dirlist = (char **)calloc(MALSIZ, sizeof (char *)); 460*5c51f124SMoriah Waterland if (dirlist == NULL) { 461*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 462*5c51f124SMoriah Waterland quit(99); 463*5c51f124SMoriah Waterland } 464*5c51f124SMoriah Waterland return; 465*5c51f124SMoriah Waterland } 466*5c51f124SMoriah Waterland 467*5c51f124SMoriah Waterland pt = path; 468*5c51f124SMoriah Waterland if (*pt == '/') 469*5c51f124SMoriah Waterland pt++; 470*5c51f124SMoriah Waterland /* 471*5c51f124SMoriah Waterland * since the pathname supplied is never just a directory, 472*5c51f124SMoriah Waterland * we store only the dirname of of the path. 473*5c51f124SMoriah Waterland */ 474*5c51f124SMoriah Waterland while (pt = strchr(pt, '/')) { 475*5c51f124SMoriah Waterland *pt = '\0'; 476*5c51f124SMoriah Waterland found = 0; 477*5c51f124SMoriah Waterland for (i = 0; dirlist[i] != NULL; i++) { 478*5c51f124SMoriah Waterland if (strcmp(path, dirlist[i]) == 0) { 479*5c51f124SMoriah Waterland found++; 480*5c51f124SMoriah Waterland break; 481*5c51f124SMoriah Waterland } 482*5c51f124SMoriah Waterland } 483*5c51f124SMoriah Waterland if (!found) { 484*5c51f124SMoriah Waterland /* insert this path in node list */ 485*5c51f124SMoriah Waterland dirlist[i] = qstrdup(path); 486*5c51f124SMoriah Waterland if ((++i % MALSIZ) == 0) { 487*5c51f124SMoriah Waterland dirlist = (char **)realloc(dirlist, 488*5c51f124SMoriah Waterland (i+MALSIZ) * sizeof (char *)); 489*5c51f124SMoriah Waterland if (dirlist == NULL) { 490*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 491*5c51f124SMoriah Waterland quit(99); 492*5c51f124SMoriah Waterland } 493*5c51f124SMoriah Waterland } 494*5c51f124SMoriah Waterland dirlist[i] = (char *)NULL; 495*5c51f124SMoriah Waterland } 496*5c51f124SMoriah Waterland *pt++ = '/'; 497*5c51f124SMoriah Waterland } 498*5c51f124SMoriah Waterland } 499*5c51f124SMoriah Waterland 500*5c51f124SMoriah Waterland static int 501*5c51f124SMoriah Waterland nodecount(char *path) 502*5c51f124SMoriah Waterland { 503*5c51f124SMoriah Waterland char *pt; 504*5c51f124SMoriah Waterland int i, found, count; 505*5c51f124SMoriah Waterland 506*5c51f124SMoriah Waterland pt = path; 507*5c51f124SMoriah Waterland if (*pt == '/') 508*5c51f124SMoriah Waterland pt++; 509*5c51f124SMoriah Waterland 510*5c51f124SMoriah Waterland /* 511*5c51f124SMoriah Waterland * we want to count the number of path 512*5c51f124SMoriah Waterland * segments that need to be created, not 513*5c51f124SMoriah Waterland * including the basename of the path; 514*5c51f124SMoriah Waterland * this works only since we are never 515*5c51f124SMoriah Waterland * passed a pathname which itself is a 516*5c51f124SMoriah Waterland * directory 517*5c51f124SMoriah Waterland */ 518*5c51f124SMoriah Waterland count = 0; 519*5c51f124SMoriah Waterland while (pt = strchr(pt, '/')) { 520*5c51f124SMoriah Waterland *pt = '\0'; 521*5c51f124SMoriah Waterland found = 0; 522*5c51f124SMoriah Waterland for (i = 0; dirlist[i]; i++) { 523*5c51f124SMoriah Waterland if (strcmp(path, dirlist[i]) != 0) { 524*5c51f124SMoriah Waterland found++; 525*5c51f124SMoriah Waterland break; 526*5c51f124SMoriah Waterland } 527*5c51f124SMoriah Waterland } 528*5c51f124SMoriah Waterland if (!found) 529*5c51f124SMoriah Waterland count++; 530*5c51f124SMoriah Waterland *pt++ = '/'; 531*5c51f124SMoriah Waterland } 532*5c51f124SMoriah Waterland return (count); 533*5c51f124SMoriah Waterland } 534*5c51f124SMoriah Waterland 535*5c51f124SMoriah Waterland static void 536*5c51f124SMoriah Waterland newvolume(struct data **sf, unsigned int eptnum, fsblkcnt_t limit, 537*5c51f124SMoriah Waterland fsblkcnt_t ilimit) 538*5c51f124SMoriah Waterland { 539*5c51f124SMoriah Waterland register int i; 540*5c51f124SMoriah Waterland int newnodes; 541*5c51f124SMoriah Waterland 542*5c51f124SMoriah Waterland if (volno) { 543*5c51f124SMoriah Waterland (void) fprintf(stderr, 544*5c51f124SMoriah Waterland gettext("part %2d -- %llu blocks, %llu entries\n"), 545*5c51f124SMoriah Waterland volno, btotal, ftotal); 546*5c51f124SMoriah Waterland if (btotal > bmax) 547*5c51f124SMoriah Waterland bmax = btotal; 548*5c51f124SMoriah Waterland if (ftotal > fmax) 549*5c51f124SMoriah Waterland fmax = ftotal; 550*5c51f124SMoriah Waterland btotal = bpkginfo + 2ULL; 551*5c51f124SMoriah Waterland ftotal = 2; 552*5c51f124SMoriah Waterland } else { 553*5c51f124SMoriah Waterland btotal = 2ULL; 554*5c51f124SMoriah Waterland ftotal = 1; 555*5c51f124SMoriah Waterland } 556*5c51f124SMoriah Waterland volno++; 557*5c51f124SMoriah Waterland 558*5c51f124SMoriah Waterland /* 559*5c51f124SMoriah Waterland * zero out directory storage 560*5c51f124SMoriah Waterland */ 561*5c51f124SMoriah Waterland allocnode((char *)0); 562*5c51f124SMoriah Waterland 563*5c51f124SMoriah Waterland /* 564*5c51f124SMoriah Waterland * force storage of files whose volume number has already been assigned 565*5c51f124SMoriah Waterland */ 566*5c51f124SMoriah Waterland for (i = 0; i < eptnum; i++) { 567*5c51f124SMoriah Waterland if (sf[i]->ept->volno == volno) { 568*5c51f124SMoriah Waterland newnodes = nodecount(sf[i]->ept->path); 569*5c51f124SMoriah Waterland ftotal += newnodes + 1; 570*5c51f124SMoriah Waterland btotal += sf[i]->blks + (newnodes * DIRSIZE); 571*5c51f124SMoriah Waterland if (btotal > limit) { 572*5c51f124SMoriah Waterland progerr(gettext(ERR_VOLBLKS), volno, btotal, 573*5c51f124SMoriah Waterland limit); 574*5c51f124SMoriah Waterland quit(1); 575*5c51f124SMoriah Waterland } else if ((ilimit == 0) && (ftotal+1 > ilimit)) { 576*5c51f124SMoriah Waterland progerr(gettext(ERR_VOLFILES), volno, ftotal+1, 577*5c51f124SMoriah Waterland ilimit); 578*5c51f124SMoriah Waterland quit(1); 579*5c51f124SMoriah Waterland } 580*5c51f124SMoriah Waterland } 581*5c51f124SMoriah Waterland } 582*5c51f124SMoriah Waterland } 583*5c51f124SMoriah Waterland 584*5c51f124SMoriah Waterland static void 585*5c51f124SMoriah Waterland addclass(char *aclass, int vol) 586*5c51f124SMoriah Waterland { 587*5c51f124SMoriah Waterland int i; 588*5c51f124SMoriah Waterland 589*5c51f124SMoriah Waterland for (i = 0; i < nclass; ++i) { 590*5c51f124SMoriah Waterland if (strcmp(cl[i].name, aclass) == 0) { 591*5c51f124SMoriah Waterland if (vol <= 0) 592*5c51f124SMoriah Waterland return; 593*5c51f124SMoriah Waterland if (!cl[i].first || (vol < cl[i].first)) 594*5c51f124SMoriah Waterland cl[i].first = vol; 595*5c51f124SMoriah Waterland if (vol > cl[i].last) 596*5c51f124SMoriah Waterland cl[i].last = vol; 597*5c51f124SMoriah Waterland return; 598*5c51f124SMoriah Waterland } 599*5c51f124SMoriah Waterland } 600*5c51f124SMoriah Waterland cl[nclass].name = qstrdup(aclass); 601*5c51f124SMoriah Waterland cl[nclass].first = vol; 602*5c51f124SMoriah Waterland cl[nclass].last = vol; 603*5c51f124SMoriah Waterland if ((++nclass % MALSIZ) == 0) { 604*5c51f124SMoriah Waterland cl = (struct class_type *)realloc((char *)cl, 605*5c51f124SMoriah Waterland sizeof (struct class_type) * (nclass+MALSIZ)); 606*5c51f124SMoriah Waterland if (!cl) { 607*5c51f124SMoriah Waterland progerr(gettext(ERR_MEMORY), errno); 608*5c51f124SMoriah Waterland quit(99); 609*5c51f124SMoriah Waterland } 610*5c51f124SMoriah Waterland } 611*5c51f124SMoriah Waterland } 612*5c51f124SMoriah Waterland 613*5c51f124SMoriah Waterland static void 614*5c51f124SMoriah Waterland sortsize(struct data *f, struct data **sf, unsigned int eptnum) 615*5c51f124SMoriah Waterland { 616*5c51f124SMoriah Waterland int nsf; 617*5c51f124SMoriah Waterland int j, k; 618*5c51f124SMoriah Waterland unsigned int i; 619*5c51f124SMoriah Waterland 620*5c51f124SMoriah Waterland nsf = 0; 621*5c51f124SMoriah Waterland for (i = 0; i < eptnum; i++) { 622*5c51f124SMoriah Waterland for (j = 0; j < nsf; ++j) { 623*5c51f124SMoriah Waterland if (f[i].blks > sf[j]->blks) { 624*5c51f124SMoriah Waterland for (k = nsf; k > j; k--) { 625*5c51f124SMoriah Waterland sf[k] = sf[k-1]; 626*5c51f124SMoriah Waterland } 627*5c51f124SMoriah Waterland break; 628*5c51f124SMoriah Waterland } 629*5c51f124SMoriah Waterland } 630*5c51f124SMoriah Waterland sf[j] = &f[i]; 631*5c51f124SMoriah Waterland nsf++; 632*5c51f124SMoriah Waterland } 633*5c51f124SMoriah Waterland } 634