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
splpkgmap(struct cfent ** eptlist,unsigned int eptnum,char * order[],ulong_t bsize,ulong_t frsize,fsblkcnt_t * plimit,fsfilcnt_t * pilimit,fsblkcnt_t * pllimit)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
store(struct data ** sf,unsigned int eptnum,char * aclass,fsblkcnt_t limit,fsfilcnt_t ilimit)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
allocnode(char * path)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
nodecount(char * path)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
newvolume(struct data ** sf,unsigned int eptnum,fsblkcnt_t limit,fsblkcnt_t ilimit)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
addclass(char * aclass,int vol)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
sortsize(struct data * f,struct data ** sf,unsigned int eptnum)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