xref: /onnv-gate/usr/src/cmd/svr4pkg/pkgmk/splpkgmap.c (revision 9781:ccf49524d5dc)
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