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