putcfile.c revision 9781:ccf49524d5dc
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
49int
50putcfile(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, " %d", 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, " %d", 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
217int
218putcvfpfile(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