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