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 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 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