1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <sys/types.h>
36 #include "pkgstrct.h"
37 #include "pkglib.h"
38 
39 /*
40  * Name:	putcfile
41  * Description:	Write contents file entry to specified FILE
42  * Arguments:	struct cfent a_ept - data for contents file entry
43  *		FILE *a_fp - FP of file to write contents file entry to
44  * Notes:	This is identical to putcvfpfile() but this function takes a
45  *		stdio FILE* file to write to instead of a VFP_T file. It is
46  *		MUCH slower than putcvfpfile().
47  */
48 
49 int
putcfile(struct cfent * a_ept,FILE * a_fp)50 putcfile(struct cfent *a_ept, FILE *a_fp)
51 {
52 	struct pinfo *pinfo;
53 
54 	if (a_ept->ftype == 'i') {
55 		return (0); /* no ifiles stored in contents DB */
56 	}
57 
58 	if (a_ept->path == NULL) {
59 		return (-1);	/* no path name - no entry to write */
60 	}
61 
62 	if (fputs(a_ept->path, a_fp) == EOF) {
63 		return (-1);
64 	}
65 
66 	if (a_ept->ainfo.local) {
67 		if (putc('=', a_fp) == EOF) {
68 			return (-1);
69 		}
70 		if (fputs(a_ept->ainfo.local, a_fp) == EOF)
71 			return (-1);
72 	}
73 
74 	if (a_ept->volno) {
75 		if (fprintf(a_fp, " %d", a_ept->volno) < 0) {
76 			return (-1);
77 		}
78 	}
79 
80 	if (putc(' ', a_fp) == EOF) {
81 		return (-1);
82 	}
83 
84 	if (putc(a_ept->ftype, a_fp) == EOF) {
85 		return (-1);
86 	}
87 
88 	if (putc(' ', a_fp) == EOF) {
89 		return (-1);
90 	}
91 
92 	if (fputs(a_ept->pkg_class, a_fp) == EOF) {
93 		return (-1);
94 	}
95 
96 	if ((a_ept->ftype == 'c') || (a_ept->ftype == 'b')) {
97 		if (a_ept->ainfo.major == BADMAJOR) {
98 			if (putc(' ', a_fp) == EOF) {
99 				return (-1);
100 			}
101 
102 			if (putc('?', a_fp) == EOF) {
103 				return (-1);
104 			}
105 		} else {
106 			if (fprintf(a_fp, " %ld", a_ept->ainfo.major) < 0)
107 				return (-1);
108 		}
109 
110 		if (a_ept->ainfo.minor == BADMINOR) {
111 			if (putc(' ', a_fp) == EOF) {
112 				return (-1);
113 			}
114 
115 			if (putc('?', a_fp) == EOF) {
116 				return (-1);
117 			}
118 		} else {
119 			if (fprintf(a_fp, " %ld", a_ept->ainfo.minor) < 0)
120 				return (-1);
121 		}
122 	}
123 
124 	if ((a_ept->ftype == 'd') || (a_ept->ftype == 'x') ||
125 		(a_ept->ftype == 'c') || (a_ept->ftype == 'b') ||
126 		(a_ept->ftype == 'p') || (a_ept->ftype == 'f') ||
127 		(a_ept->ftype == 'v') || (a_ept->ftype == 'e')) {
128 		if (fprintf(a_fp,
129 			((a_ept->ainfo.mode == BADMODE) ? " ?" : " %04o"),
130 			a_ept->ainfo.mode) < 0)
131 			return (-1);
132 
133 		if (putc(' ', a_fp) == EOF) {
134 			return (-1);
135 		}
136 
137 		if (fputs(a_ept->ainfo.owner, a_fp) == EOF) {
138 			return (-1);
139 		}
140 
141 		if (putc(' ', a_fp) == EOF) {
142 			return (-1);
143 		}
144 
145 		if (fputs(a_ept->ainfo.group, a_fp) == EOF) {
146 			return (-1);
147 		}
148 	}
149 
150 	if ((a_ept->ftype == 'f') || (a_ept->ftype == 'v') ||
151 		(a_ept->ftype == 'e')) {
152 		if (fprintf(a_fp,
153 			((a_ept->cinfo.size == BADCONT) ? " ?" : " %llu"),
154 			a_ept->cinfo.size) < 0)
155 			return (-1);
156 
157 		if (fprintf(a_fp,
158 			((a_ept->cinfo.cksum == BADCONT) ? " ?" : " %ld"),
159 			a_ept->cinfo.cksum) < 0)
160 			return (-1);
161 
162 		if (fprintf(a_fp,
163 		    ((a_ept->cinfo.modtime == BADCONT) ? " ?" : " %ld"),
164 		    a_ept->cinfo.modtime) < 0)
165 			return (-1);
166 	}
167 
168 	pinfo = a_ept->pinfo;
169 	while (pinfo) {
170 		if (putc(' ', a_fp) == EOF) {
171 			return (-1);
172 		}
173 
174 		if (pinfo->status) {
175 			if (fputc(pinfo->status, a_fp) == EOF) {
176 				return (-1);
177 			}
178 		}
179 
180 		if (fputs(pinfo->pkg, a_fp) == EOF) {
181 			return (-1);
182 		}
183 
184 		if (pinfo->editflag) {
185 			if (putc('\\', a_fp) == EOF) {
186 				return (-1);
187 			}
188 		}
189 
190 		if (pinfo->aclass[0]) {
191 			if (putc(':', a_fp) == EOF) {
192 				return (-1);
193 			}
194 			if (fputs(pinfo->aclass, a_fp) == EOF) {
195 				return (-1);
196 			}
197 		}
198 		pinfo = pinfo->next;
199 	}
200 
201 	if (putc('\n', a_fp) == EOF) {
202 		return (-1);
203 	}
204 	return (0);
205 }
206 
207 /*
208  * Name:	putcvfpfile
209  * Description:	Write contents file entry to specified VFP
210  * Arguments:	struct cfent a_ept - data for contents file entry
211  *		VFP_T *a_vfp - VFP of file to write contents file entry to
212  * Notes:	This is identical to putcfile() but this function takes a
213  *		VFP_T file to write to instead of a stdio FILE file. It is
214  *		MUCH faster tha putcfile().
215  */
216 
217 int
putcvfpfile(struct cfent * a_ept,VFP_T * a_vfp)218 putcvfpfile(struct cfent *a_ept, VFP_T *a_vfp)
219 {
220 	struct pinfo *pinfo;
221 
222 	/* contents file does not maintain any 'i' file entries */
223 
224 	if (a_ept->ftype == 'i') {
225 		return (0);
226 	}
227 
228 	/* cannot create an entry if it has no file name */
229 
230 	if (a_ept->path == NULL) {
231 		return (-1);
232 	}
233 
234 	/*
235 	 * Format of contents file line could be one of:
236 	 * /file=./dir/file s class SUNWxxx
237 	 * /file=../dir/file l class SUNWxxx
238 	 * /dir d class mode owner group SUNWxxx SUNWyyy
239 	 * /devices/name c class major minor mode owner group SUNWxxx
240 	 * /file f class mode owner group size cksum modtime SUNWxxx
241 	 * /file x class mode owner group SUNWppro
242 	 * /file v class mode owner group size cksum modtime SUNWxxx
243 	 * /file e class mode owner group size cksum modtime SUNWxxx
244 	 * The package name could be prefixed by one of the following
245 	 * status indicators: +-*!%@#~
246 	 */
247 
248 	/*
249 	 * Adding an entry to the specified VFP.  During normal processing the
250 	 * contents file is copied to a temporary contents file and entries are
251 	 * added as appropriate.  When this processing is completed, a decision
252 	 * is made on whether or not to overwrite the real contents file with
253 	 * the contents of the temporary contents file.  If the temporary
254 	 * contents file is just a copy of the real contents file then there is
255 	 * no need to overwrite the real contents file with the contents of the
256 	 * temporary contents file.  This decision is made in part on whether
257 	 * or not any new or modified entries have been added to the temporary
258 	 * contents file.  Set the "data is modified" indication associated
259 	 * with this VFP so that the real contents file is overwritten when
260 	 * processing is done.
261 	 */
262 
263 	(void) vfpSetModified(a_vfp);
264 
265 	/* write initial path [all entries] */
266 
267 	vfpPuts(a_vfp, a_ept->path);
268 
269 	/* if link, write out '=' portion */
270 
271 	if (a_ept->ainfo.local) {
272 		vfpPutc(a_vfp, '=');
273 		vfpPuts(a_vfp, a_ept->ainfo.local);
274 	}
275 
276 	/* if volume, write it out */
277 
278 	if (a_ept->volno) {
279 		vfpPutc(a_vfp, ' ');
280 		vfpPutInteger(a_vfp, a_ept->volno);
281 	}
282 
283 	/* write out <space><entry type><space>class> */
284 
285 	vfpPutc(a_vfp, ' ');
286 	vfpPutc(a_vfp, a_ept->ftype);
287 	vfpPutc(a_vfp, ' ');
288 	vfpPuts(a_vfp, a_ept->pkg_class);
289 
290 	/* if char/block device, write out major/minor numbers */
291 
292 	if ((a_ept->ftype == 'c') || (a_ept->ftype == 'b')) {
293 		/* major device number */
294 		if (a_ept->ainfo.major == BADMAJOR) {
295 			vfpPutc(a_vfp, ' ');
296 			vfpPutc(a_vfp, '?');
297 		} else {
298 			vfpPutc(a_vfp, ' ');
299 			vfpPutInteger(a_vfp, a_ept->ainfo.major);
300 		}
301 
302 		/* minor device number */
303 		if (a_ept->ainfo.minor == BADMINOR) {
304 			vfpPutc(a_vfp, ' ');
305 			vfpPutc(a_vfp, '?');
306 		} else {
307 			vfpPutc(a_vfp, ' ');
308 			vfpPutInteger(a_vfp, a_ept->ainfo.minor);
309 		}
310 	}
311 
312 	/* if dxcbpfve, write out mode, owner, group */
313 
314 	if ((a_ept->ftype == 'd') || (a_ept->ftype == 'x') ||
315 		(a_ept->ftype == 'c') || (a_ept->ftype == 'b') ||
316 		(a_ept->ftype == 'p') || (a_ept->ftype == 'f') ||
317 		(a_ept->ftype == 'v') || (a_ept->ftype == 'e')) {
318 
319 		/* mode */
320 		vfpPutFormat(a_vfp,
321 			((a_ept->ainfo.mode == BADMODE) ? " ?" : " %04o"),
322 			a_ept->ainfo.mode);
323 
324 		/* owner */
325 		vfpPutc(a_vfp, ' ');
326 		vfpPuts(a_vfp, a_ept->ainfo.owner);
327 
328 		/* group */
329 		vfpPutc(a_vfp, ' ');
330 		vfpPuts(a_vfp, a_ept->ainfo.group);
331 	}
332 	/* if f/v/e, write out size, cksum, modtime */
333 
334 	if ((a_ept->ftype == 'f') || (a_ept->ftype == 'v') ||
335 		(a_ept->ftype == 'e')) {
336 		/* size */
337 		vfpPutFormat(a_vfp,
338 			((a_ept->cinfo.size == BADCONT) ? " ?" : " %llu"),
339 			a_ept->cinfo.size);
340 
341 		/* cksum */
342 		vfpPutFormat(a_vfp,
343 			((a_ept->cinfo.cksum == BADCONT) ? " ?" : " %ld"),
344 			a_ept->cinfo.cksum);
345 
346 		/* modtime */
347 		vfpPutFormat(a_vfp,
348 			((a_ept->cinfo.modtime == BADCONT) ? " ?" : " %ld"),
349 			a_ept->cinfo.modtime);
350 	}
351 
352 	/* write out list of all packages referencing this entry */
353 
354 	pinfo = a_ept->pinfo;
355 	while (pinfo) {
356 		vfpPutc(a_vfp, ' ');
357 		if (pinfo->status) {
358 			vfpPutc(a_vfp, pinfo->status);
359 		}
360 
361 		vfpPuts(a_vfp, pinfo->pkg);
362 
363 		if (pinfo->editflag) {
364 			vfpPutc(a_vfp, '\\');
365 		}
366 
367 		if (pinfo->aclass[0]) {
368 			vfpPutc(a_vfp, ':');
369 			vfpPuts(a_vfp, pinfo->aclass);
370 		}
371 		pinfo = pinfo->next;
372 	}
373 
374 	vfpPutc(a_vfp, '\n');
375 	return (0);
376 }
377