| 1 |
/** $MirOS: src/bin/pax/cpio.c,v 1.12 2007/02/17 05:07:12 tg Exp $ */ |
| 2 |
/* $OpenBSD: cpio.c,v 1.17 2004/04/16 22:50:23 deraadt Exp $ */ |
| 3 |
/* $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $ */ |
| 4 |
|
| 5 |
/*- |
| 6 |
* Copyright (c) 2005 Thorsten Glaser <tg@66h.42h.de> |
| 7 |
* Copyright (c) 1992 Keith Muller. |
| 8 |
* Copyright (c) 1992, 1993 |
| 9 |
* The Regents of the University of California. All rights reserved. |
| 10 |
* |
| 11 |
* This code is derived from software contributed to Berkeley by |
| 12 |
* Keith Muller of the University of California, San Diego. |
| 13 |
* |
| 14 |
* Redistribution and use in source and binary forms, with or without |
| 15 |
* modification, are permitted provided that the following conditions |
| 16 |
* are met: |
| 17 |
* 1. Redistributions of source code must retain the above copyright |
| 18 |
* notice, this list of conditions and the following disclaimer. |
| 19 |
* 2. Redistributions in binary form must reproduce the above copyright |
| 20 |
* notice, this list of conditions and the following disclaimer in the |
| 21 |
* documentation and/or other materials provided with the distribution. |
| 22 |
* 3. Neither the name of the University nor the names of its contributors |
| 23 |
* may be used to endorse or promote products derived from this software |
| 24 |
* without specific prior written permission. |
| 25 |
* |
| 26 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 27 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 28 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 29 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 30 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 31 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 32 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 33 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 34 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 35 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 36 |
* SUCH DAMAGE. |
| 37 |
*/ |
| 38 |
|
| 39 |
#include <sys/param.h> |
| 40 |
#include <sys/time.h> |
| 41 |
#include <sys/stat.h> |
| 42 |
#include <string.h> |
| 43 |
#include <stdio.h> |
| 44 |
#include <unistd.h> |
| 45 |
#include <stdlib.h> |
| 46 |
#include "pax.h" |
| 47 |
#include "cpio.h" |
| 48 |
#include "extern.h" |
| 49 |
#include "options.h" |
| 50 |
|
| 51 |
__SCCSID("@(#)cpio.c 8.1 (Berkeley) 5/31/93"); |
| 52 |
__RCSID("$MirOS: src/bin/pax/cpio.c,v 1.12 2007/02/17 05:07:12 tg Exp $"); |
| 53 |
|
| 54 |
static int rd_nm(ARCHD *, int); |
| 55 |
static int rd_ln_nm(ARCHD *); |
| 56 |
static int com_rd(ARCHD *); |
| 57 |
|
| 58 |
/* |
| 59 |
* Routines which support the different cpio versions |
| 60 |
*/ |
| 61 |
|
| 62 |
static int swp_head; /* binary cpio header byte swap */ |
| 63 |
|
| 64 |
/* |
| 65 |
* Routines common to all versions of cpio |
| 66 |
*/ |
| 67 |
|
| 68 |
/* |
| 69 |
* cpio_strd() |
| 70 |
* Fire up the hard link detection code |
| 71 |
* Return: |
| 72 |
* 0 if ok -1 otherwise (the return values of lnk_start()) |
| 73 |
*/ |
| 74 |
|
| 75 |
int |
| 76 |
cpio_strd(void) |
| 77 |
{ |
| 78 |
return(lnk_start()); |
| 79 |
} |
| 80 |
|
| 81 |
/* |
| 82 |
* cpio_trail() |
| 83 |
* Called to determine if a header block is a valid trailer. We are |
| 84 |
* passed the block, the in_sync flag (which tells us we are in resync |
| 85 |
* mode; looking for a valid header), and cnt (which starts at zero) |
| 86 |
* which is used to count the number of empty blocks we have seen so far. |
| 87 |
* Return: |
| 88 |
* 0 if a valid trailer, -1 if not a valid trailer, |
| 89 |
*/ |
| 90 |
|
| 91 |
int |
| 92 |
cpio_trail(ARCHD *arcn, char *notused __attribute__((unused)), |
| 93 |
int notused2 __attribute__((unused)), |
| 94 |
int *notused3 __attribute__((unused))) |
| 95 |
{ |
| 96 |
/* |
| 97 |
* look for trailer id in file we are about to process |
| 98 |
*/ |
| 99 |
if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0)) |
| 100 |
return(0); |
| 101 |
return(-1); |
| 102 |
} |
| 103 |
|
| 104 |
/* |
| 105 |
* com_rd() |
| 106 |
* operations common to all cpio read functions. |
| 107 |
* Return: |
| 108 |
* 0 |
| 109 |
*/ |
| 110 |
|
| 111 |
static int |
| 112 |
com_rd(ARCHD *arcn) |
| 113 |
{ |
| 114 |
arcn->skip = 0; |
| 115 |
arcn->pat = NULL; |
| 116 |
arcn->org_name = arcn->name; |
| 117 |
switch (arcn->sb.st_mode & C_IFMT) { |
| 118 |
case C_ISFIFO: |
| 119 |
arcn->type = PAX_FIF; |
| 120 |
break; |
| 121 |
case C_ISDIR: |
| 122 |
arcn->type = PAX_DIR; |
| 123 |
break; |
| 124 |
case C_ISBLK: |
| 125 |
arcn->type = PAX_BLK; |
| 126 |
break; |
| 127 |
case C_ISCHR: |
| 128 |
arcn->type = PAX_CHR; |
| 129 |
break; |
| 130 |
case C_ISLNK: |
| 131 |
arcn->type = PAX_SLK; |
| 132 |
break; |
| 133 |
case C_ISOCK: |
| 134 |
arcn->type = PAX_SCK; |
| 135 |
break; |
| 136 |
case C_ISCTG: |
| 137 |
case C_ISREG: |
| 138 |
default: |
| 139 |
/* |
| 140 |
* we have file data, set up skip (pad is set in the format |
| 141 |
* specific sections) |
| 142 |
*/ |
| 143 |
arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG; |
| 144 |
arcn->type = PAX_REG; |
| 145 |
arcn->skip = arcn->sb.st_size; |
| 146 |
break; |
| 147 |
} |
| 148 |
if (chk_lnk(arcn) < 0) |
| 149 |
return(-1); |
| 150 |
return(0); |
| 151 |
} |
| 152 |
|
| 153 |
/* |
| 154 |
* cpio_end_wr() |
| 155 |
* write the special file with the name trailer in the proper format |
| 156 |
* Return: |
| 157 |
* result of the write of the trailer from the cpio specific write func |
| 158 |
*/ |
| 159 |
|
| 160 |
int |
| 161 |
cpio_endwr(void) |
| 162 |
{ |
| 163 |
ARCHD last; |
| 164 |
|
| 165 |
/* |
| 166 |
* create a trailer request and call the proper format write function |
| 167 |
*/ |
| 168 |
memset(&last, 0, sizeof(last)); |
| 169 |
last.nlen = sizeof(TRAILER) - 1; |
| 170 |
last.type = PAX_REG; |
| 171 |
last.sb.st_nlink = 1; |
| 172 |
(void)strlcpy(last.name, TRAILER, sizeof(last.name)); |
| 173 |
return((*frmt->wr)(&last)); |
| 174 |
} |
| 175 |
|
| 176 |
/* |
| 177 |
* rd_nam() |
| 178 |
* read in the file name which follows the cpio header |
| 179 |
* Return: |
| 180 |
* 0 if ok, -1 otherwise |
| 181 |
*/ |
| 182 |
|
| 183 |
static int |
| 184 |
rd_nm(ARCHD *arcn, int nsz) |
| 185 |
{ |
| 186 |
/* |
| 187 |
* do not even try bogus values |
| 188 |
*/ |
| 189 |
if ((nsz == 0) || ((size_t)nsz > sizeof(arcn->name))) { |
| 190 |
paxwarn(1, "Cpio file name length %d is out of range", nsz); |
| 191 |
return(-1); |
| 192 |
} |
| 193 |
|
| 194 |
/* |
| 195 |
* read the name and make sure it is not empty and is \0 terminated |
| 196 |
*/ |
| 197 |
if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') || |
| 198 |
(arcn->name[0] == '\0')) { |
| 199 |
paxwarn(1, "Cpio file name in header is corrupted"); |
| 200 |
return(-1); |
| 201 |
} |
| 202 |
return(0); |
| 203 |
} |
| 204 |
|
| 205 |
/* |
| 206 |
* rd_ln_nm() |
| 207 |
* read in the link name for a file with links. The link name is stored |
| 208 |
* like file data (and is NOT \0 terminated!) |
| 209 |
* Return: |
| 210 |
* 0 if ok, -1 otherwise |
| 211 |
*/ |
| 212 |
|
| 213 |
static int |
| 214 |
rd_ln_nm(ARCHD *arcn) |
| 215 |
{ |
| 216 |
/* |
| 217 |
* check the length specified for bogus values |
| 218 |
*/ |
| 219 |
if ((arcn->sb.st_size == 0) || |
| 220 |
((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) { |
| 221 |
# ifdef LONG_OFF_T |
| 222 |
paxwarn(1, "Cpio link name length is invalid: %lu", |
| 223 |
arcn->sb.st_size); |
| 224 |
# else |
| 225 |
paxwarn(1, "Cpio link name length is invalid: %llu", |
| 226 |
arcn->sb.st_size); |
| 227 |
# endif |
| 228 |
return(-1); |
| 229 |
} |
| 230 |
|
| 231 |
/* |
| 232 |
* read in the link name and \0 terminate it |
| 233 |
*/ |
| 234 |
if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) != |
| 235 |
(int)arcn->sb.st_size) { |
| 236 |
paxwarn(1, "Cpio link name read error"); |
| 237 |
return(-1); |
| 238 |
} |
| 239 |
arcn->ln_nlen = arcn->sb.st_size; |
| 240 |
arcn->ln_name[arcn->ln_nlen] = '\0'; |
| 241 |
|
| 242 |
/* |
| 243 |
* watch out for those empty link names |
| 244 |
*/ |
| 245 |
if (arcn->ln_name[0] == '\0') { |
| 246 |
paxwarn(1, "Cpio link name is corrupt"); |
| 247 |
return(-1); |
| 248 |
} |
| 249 |
return(0); |
| 250 |
} |
| 251 |
|
| 252 |
/* |
| 253 |
* Routines common to the extended byte oriented cpio format |
| 254 |
*/ |
| 255 |
|
| 256 |
/* |
| 257 |
* cpio_id() |
| 258 |
* determine if a block given to us is a valid extended byte oriented |
| 259 |
* cpio header |
| 260 |
* Return: |
| 261 |
* 0 if a valid header, -1 otherwise |
| 262 |
*/ |
| 263 |
|
| 264 |
int |
| 265 |
cpio_id(char *blk, int size) |
| 266 |
{ |
| 267 |
if (((size_t)size < sizeof(HD_CPIO)) || |
| 268 |
(strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0)) |
| 269 |
return(-1); |
| 270 |
return(0); |
| 271 |
} |
| 272 |
|
| 273 |
/* |
| 274 |
* cpio_rd() |
| 275 |
* determine if a buffer is a byte oriented extended cpio archive entry. |
| 276 |
* convert and store the values in the ARCHD parameter. |
| 277 |
* Return: |
| 278 |
* 0 if a valid header, -1 otherwise. |
| 279 |
*/ |
| 280 |
|
| 281 |
int |
| 282 |
cpio_rd(ARCHD *arcn, char *buf) |
| 283 |
{ |
| 284 |
int nsz; |
| 285 |
HD_CPIO *hd; |
| 286 |
|
| 287 |
/* |
| 288 |
* check that this is a valid header, if not return -1 |
| 289 |
*/ |
| 290 |
if (cpio_id(buf, sizeof(HD_CPIO)) < 0) |
| 291 |
return(-1); |
| 292 |
hd = (HD_CPIO *)buf; |
| 293 |
|
| 294 |
/* |
| 295 |
* byte oriented cpio (posix) does not have padding! extract the octal |
| 296 |
* ascii fields from the header |
| 297 |
*/ |
| 298 |
arcn->pad = 0L; |
| 299 |
arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); |
| 300 |
arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); |
| 301 |
arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); |
| 302 |
arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); |
| 303 |
arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); |
| 304 |
arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), |
| 305 |
OCT); |
| 306 |
arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); |
| 307 |
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), |
| 308 |
OCT); |
| 309 |
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; |
| 310 |
# ifdef LONG_OFF_T |
| 311 |
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize), |
| 312 |
OCT); |
| 313 |
# else |
| 314 |
arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), |
| 315 |
OCT); |
| 316 |
# endif |
| 317 |
|
| 318 |
/* |
| 319 |
* check name size and if valid, read in the name of this entry (name |
| 320 |
* follows header in the archive) |
| 321 |
*/ |
| 322 |
if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) |
| 323 |
return(-1); |
| 324 |
arcn->nlen = nsz - 1; |
| 325 |
if (rd_nm(arcn, nsz) < 0) |
| 326 |
return(-1); |
| 327 |
|
| 328 |
if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { |
| 329 |
/* |
| 330 |
* no link name to read for this file |
| 331 |
*/ |
| 332 |
arcn->ln_nlen = 0; |
| 333 |
arcn->ln_name[0] = '\0'; |
| 334 |
return(com_rd(arcn)); |
| 335 |
} |
| 336 |
|
| 337 |
/* |
| 338 |
* check link name size and read in the link name. Link names are |
| 339 |
* stored like file data. |
| 340 |
*/ |
| 341 |
if (rd_ln_nm(arcn) < 0) |
| 342 |
return(-1); |
| 343 |
|
| 344 |
/* |
| 345 |
* we have a valid header (with a link) |
| 346 |
*/ |
| 347 |
return(com_rd(arcn)); |
| 348 |
} |
| 349 |
|
| 350 |
/* |
| 351 |
* cpio_endrd() |
| 352 |
* no cleanup needed here, just return size of the trailer (for append) |
| 353 |
* Return: |
| 354 |
* size of trailer header in this format |
| 355 |
*/ |
| 356 |
|
| 357 |
off_t |
| 358 |
cpio_endrd(void) |
| 359 |
{ |
| 360 |
return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER))); |
| 361 |
} |
| 362 |
|
| 363 |
/* |
| 364 |
* cpio_stwr() |
| 365 |
* start up the device mapping table |
| 366 |
* Return: |
| 367 |
* 0 if ok, -1 otherwise (what dev_start() returns) |
| 368 |
*/ |
| 369 |
|
| 370 |
int |
| 371 |
cpio_stwr(void) |
| 372 |
{ |
| 373 |
if ((anonarch & ANON_INODES) && flnk_start()) |
| 374 |
return (-1); |
| 375 |
return(dev_start()); |
| 376 |
} |
| 377 |
|
| 378 |
int |
| 379 |
dist_stwr(void) |
| 380 |
{ |
| 381 |
anonarch &= ANON_DEBUG | ANON_VERBOSE; |
| 382 |
anonarch |= ANON_UIDGID | ANON_INODES | ANON_HARDLINKS; |
| 383 |
return(cpio_stwr()); |
| 384 |
} |
| 385 |
|
| 386 |
/* |
| 387 |
* cpio_wr() |
| 388 |
* copy the data in the ARCHD to buffer in extended byte oriented cpio |
| 389 |
* format. |
| 390 |
* Return |
| 391 |
* 0 if file has data to be written after the header, 1 if file has NO |
| 392 |
* data to write after the header, -1 if archive write failed |
| 393 |
*/ |
| 394 |
|
| 395 |
int |
| 396 |
cpio_wr(ARCHD *arcn) |
| 397 |
{ |
| 398 |
HD_CPIO *hd; |
| 399 |
int nsz; |
| 400 |
char hdblk[sizeof(HD_CPIO)]; |
| 401 |
|
| 402 |
u_long t_uid, t_gid, t_mtime, t_dev; |
| 403 |
ino_t t_ino; |
| 404 |
|
| 405 |
anonarch_init(); |
| 406 |
|
| 407 |
/* |
| 408 |
* check and repair truncated device and inode fields in the header |
| 409 |
*/ |
| 410 |
if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0) |
| 411 |
return(-1); |
| 412 |
|
| 413 |
arcn->pad = 0L; |
| 414 |
nsz = arcn->nlen + 1; |
| 415 |
hd = (HD_CPIO *)hdblk; |
| 416 |
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) |
| 417 |
arcn->sb.st_rdev = 0; |
| 418 |
|
| 419 |
t_uid = (anonarch & ANON_UIDGID) ? 0UL : (u_long)arcn->sb.st_uid; |
| 420 |
t_gid = (anonarch & ANON_UIDGID) ? 0UL : (u_long)arcn->sb.st_gid; |
| 421 |
t_mtime = (anonarch & ANON_MTIME) ? 0UL : (u_long)arcn->sb.st_mtime; |
| 422 |
t_ino = (anonarch & ANON_INODES) ? (ino_t)chk_flnk(arcn) : |
| 423 |
arcn->sb.st_ino; |
| 424 |
t_dev = (anonarch & ANON_INODES) ? 0UL : (u_long)arcn->sb.st_dev; |
| 425 |
if (!cpio_trail(arcn, NULL, 0, NULL)) |
| 426 |
t_ino = 0UL; |
| 427 |
if (t_ino == (ino_t)-1) { |
| 428 |
paxwarn(1, "Invalid inode number for file %s", arcn->org_name); |
| 429 |
return (1); |
| 430 |
} |
| 431 |
if (!(anonarch & ANON_HARDLINKS)) |
| 432 |
arcn->type &= ~PAX_LINKOR; |
| 433 |
|
| 434 |
switch (arcn->type) { |
| 435 |
case PAX_CTG: |
| 436 |
case PAX_REG: |
| 437 |
case PAX_HRG: |
| 438 |
/* |
| 439 |
* set data size for file data |
| 440 |
*/ |
| 441 |
# ifdef LONG_OFF_T |
| 442 |
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, |
| 443 |
sizeof(hd->c_filesize), OCT)) { |
| 444 |
# else |
| 445 |
if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, |
| 446 |
sizeof(hd->c_filesize), OCT)) { |
| 447 |
# endif |
| 448 |
paxwarn(1,"File is too large for cpio format %s", |
| 449 |
arcn->org_name); |
| 450 |
return(1); |
| 451 |
} |
| 452 |
break; |
| 453 |
case PAX_SLK: |
| 454 |
/* |
| 455 |
* set data size to hold link name |
| 456 |
*/ |
| 457 |
if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, |
| 458 |
sizeof(hd->c_filesize), OCT)) |
| 459 |
goto out; |
| 460 |
break; |
| 461 |
default: |
| 462 |
/* |
| 463 |
* all other file types have no file data |
| 464 |
*/ |
| 465 |
if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), |
| 466 |
OCT)) |
| 467 |
goto out; |
| 468 |
break; |
| 469 |
} |
| 470 |
|
| 471 |
if (anonarch & ANON_DEBUG) |
| 472 |
paxwarn(0, "writing dev %lX inode %10lX mode %8lo user %ld:%ld" |
| 473 |
"\n\tnlink %3ld mtime %08lX name '%s'", t_dev, |
| 474 |
(u_long)t_ino, (u_long)arcn->sb.st_mode, t_uid, t_gid, |
| 475 |
(u_long)arcn->sb.st_nlink, t_mtime, arcn->name); |
| 476 |
|
| 477 |
/* |
| 478 |
* copy the values to the header using octal ascii |
| 479 |
*/ |
| 480 |
if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || |
| 481 |
ul_asc(t_dev, hd->c_dev, sizeof(hd->c_dev), |
| 482 |
OCT) || |
| 483 |
ul_asc((u_long)t_ino, hd->c_ino, sizeof(hd->c_ino), |
| 484 |
OCT) || |
| 485 |
ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), |
| 486 |
OCT) || |
| 487 |
ul_asc(t_uid, hd->c_uid, sizeof(hd->c_uid), |
| 488 |
OCT) || |
| 489 |
ul_asc(t_gid, hd->c_gid, sizeof(hd->c_gid), |
| 490 |
OCT) || |
| 491 |
ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), |
| 492 |
OCT) || |
| 493 |
ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), |
| 494 |
OCT) || |
| 495 |
ul_asc(t_mtime,hd->c_mtime,sizeof(hd->c_mtime), |
| 496 |
OCT) || |
| 497 |
ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) |
| 498 |
goto out; |
| 499 |
|
| 500 |
/* |
| 501 |
* write the file name to the archive |
| 502 |
*/ |
| 503 |
if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) || |
| 504 |
(wr_rdbuf(arcn->name, nsz) < 0)) { |
| 505 |
paxwarn(1, "Unable to write cpio header for %s", arcn->org_name); |
| 506 |
return(-1); |
| 507 |
} |
| 508 |
|
| 509 |
/* |
| 510 |
* if this file has data, we are done. The caller will write the file |
| 511 |
* data, if we are link tell caller we are done, go to next file |
| 512 |
*/ |
| 513 |
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || |
| 514 |
(arcn->type == PAX_HRG)) |
| 515 |
return(0); |
| 516 |
if (arcn->type & PAX_LINKOR) { |
| 517 |
arcn->type &= ~PAX_LINKOR; |
| 518 |
return (1); |
| 519 |
} |
| 520 |
if (arcn->type != PAX_SLK) |
| 521 |
return(1); |
| 522 |
|
| 523 |
/* |
| 524 |
* write the link name to the archive, tell the caller to go to the |
| 525 |
* next file as we are done. |
| 526 |
*/ |
| 527 |
if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) { |
| 528 |
paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name); |
| 529 |
return(-1); |
| 530 |
} |
| 531 |
return(1); |
| 532 |
|
| 533 |
out: |
| 534 |
/* |
| 535 |
* header field is out of range |
| 536 |
*/ |
| 537 |
paxwarn(1, "Cpio header field is too small to store file %s", |
| 538 |
arcn->org_name); |
| 539 |
return(1); |
| 540 |
} |
| 541 |
|
| 542 |
/* |
| 543 |
* Routines common to the system VR4 version of cpio (with/without file CRC) |
| 544 |
*/ |
| 545 |
|
| 546 |
/* |
| 547 |
* vcpio_id() |
| 548 |
* determine if a block given to us is a valid system VR4 cpio header |
| 549 |
* WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header |
| 550 |
* uses HEX |
| 551 |
* Return: |
| 552 |
* 0 if a valid header, -1 otherwise |
| 553 |
*/ |
| 554 |
|
| 555 |
int |
| 556 |
vcpio_id(char *blk, int size) |
| 557 |
{ |
| 558 |
if (((size_t)size < sizeof(HD_VCPIO)) || |
| 559 |
(strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0)) |
| 560 |
return(-1); |
| 561 |
return(0); |
| 562 |
} |
| 563 |
|
| 564 |
/* |
| 565 |
* crc_id() |
| 566 |
* determine if a block given to us is a valid system VR4 cpio header |
| 567 |
* WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX |
| 568 |
* Return: |
| 569 |
* 0 if a valid header, -1 otherwise |
| 570 |
*/ |
| 571 |
|
| 572 |
int |
| 573 |
crc_id(char *blk, int size) |
| 574 |
{ |
| 575 |
if (((size_t)size < sizeof(HD_VCPIO)) || |
| 576 |
(strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0)) |
| 577 |
return(-1); |
| 578 |
return(0); |
| 579 |
} |
| 580 |
|
| 581 |
/* |
| 582 |
* crc_strd() |
| 583 |
w set file data CRC calculations. Fire up the hard link detection code |
| 584 |
* Return: |
| 585 |
* 0 if ok -1 otherwise (the return values of lnk_start()) |
| 586 |
*/ |
| 587 |
|
| 588 |
int |
| 589 |
crc_strd(void) |
| 590 |
{ |
| 591 |
docrc = 1; |
| 592 |
return(lnk_start()); |
| 593 |
} |
| 594 |
|
| 595 |
/* |
| 596 |
* vcpio_rd() |
| 597 |
* determine if a buffer is a system VR4 archive entry. (with/without CRC) |
| 598 |
* convert and store the values in the ARCHD parameter. |
| 599 |
* Return: |
| 600 |
* 0 if a valid header, -1 otherwise. |
| 601 |
*/ |
| 602 |
|
| 603 |
int |
| 604 |
vcpio_rd(ARCHD *arcn, char *buf) |
| 605 |
{ |
| 606 |
HD_VCPIO *hd; |
| 607 |
dev_t devminor; |
| 608 |
dev_t devmajor; |
| 609 |
int nsz; |
| 610 |
|
| 611 |
/* |
| 612 |
* during the id phase it was determined if we were using CRC, use the |
| 613 |
* proper id routine. |
| 614 |
*/ |
| 615 |
if (docrc) { |
| 616 |
if (crc_id(buf, sizeof(HD_VCPIO)) < 0) |
| 617 |
return(-1); |
| 618 |
} else { |
| 619 |
if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0) |
| 620 |
return(-1); |
| 621 |
} |
| 622 |
|
| 623 |
hd = (HD_VCPIO *)buf; |
| 624 |
arcn->pad = 0L; |
| 625 |
|
| 626 |
/* |
| 627 |
* extract the hex ascii fields from the header |
| 628 |
*/ |
| 629 |
arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); |
| 630 |
arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); |
| 631 |
arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); |
| 632 |
arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); |
| 633 |
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); |
| 634 |
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; |
| 635 |
# ifdef LONG_OFF_T |
| 636 |
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize, |
| 637 |
sizeof(hd->c_filesize), HEX); |
| 638 |
# else |
| 639 |
arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, |
| 640 |
sizeof(hd->c_filesize), HEX); |
| 641 |
# endif |
| 642 |
arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), |
| 643 |
HEX); |
| 644 |
devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); |
| 645 |
devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); |
| 646 |
arcn->sb.st_dev = TODEV(devmajor, devminor); |
| 647 |
devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_rmaj), HEX); |
| 648 |
devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_rmin), HEX); |
| 649 |
arcn->sb.st_rdev = TODEV(devmajor, devminor); |
| 650 |
arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); |
| 651 |
|
| 652 |
/* |
| 653 |
* check the length of the file name, if ok read it in, return -1 if |
| 654 |
* bogus |
| 655 |
*/ |
| 656 |
if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) |
| 657 |
return(-1); |
| 658 |
arcn->nlen = nsz - 1; |
| 659 |
if (rd_nm(arcn, nsz) < 0) |
| 660 |
return(-1); |
| 661 |
|
| 662 |
/* |
| 663 |
* skip padding. header + filename is aligned to 4 byte boundaries |
| 664 |
*/ |
| 665 |
if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0) |
| 666 |
return(-1); |
| 667 |
|
| 668 |
/* |
| 669 |
* if not a link (or a file with no data), calculate pad size (for |
| 670 |
* padding which follows the file data), clear the link name and return |
| 671 |
*/ |
| 672 |
if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { |
| 673 |
/* |
| 674 |
* we have a valid header (not a link) |
| 675 |
*/ |
| 676 |
arcn->ln_nlen = 0; |
| 677 |
arcn->ln_name[0] = '\0'; |
| 678 |
arcn->pad = VCPIO_PAD(arcn->sb.st_size); |
| 679 |
return(com_rd(arcn)); |
| 680 |
} |
| 681 |
|
| 682 |
/* |
| 683 |
* read in the link name and skip over the padding |
| 684 |
*/ |
| 685 |
if ((rd_ln_nm(arcn) < 0) || |
| 686 |
(rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0)) |
| 687 |
return(-1); |
| 688 |
|
| 689 |
/* |
| 690 |
* we have a valid header (with a link) |
| 691 |
*/ |
| 692 |
return(com_rd(arcn)); |
| 693 |
} |
| 694 |
|
| 695 |
/* |
| 696 |
* vcpio_endrd() |
| 697 |
* no cleanup needed here, just return size of the trailer (for append) |
| 698 |
* Return: |
| 699 |
* size of trailer header in this format |
| 700 |
*/ |
| 701 |
|
| 702 |
off_t |
| 703 |
vcpio_endrd(void) |
| 704 |
{ |
| 705 |
return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) + |
| 706 |
(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))))); |
| 707 |
} |
| 708 |
|
| 709 |
/* |
| 710 |
* crc_stwr() |
| 711 |
* start up the device mapping table, enable crc file calculation |
| 712 |
* Return: |
| 713 |
* 0 if ok, -1 otherwise (what dev_start() returns) |
| 714 |
*/ |
| 715 |
|
| 716 |
int |
| 717 |
crc_stwr(void) |
| 718 |
{ |
| 719 |
docrc = 1; |
| 720 |
if ((anonarch & ANON_INODES) && flnk_start()) |
| 721 |
return (-1); |
| 722 |
return(dev_start()); |
| 723 |
} |
| 724 |
|
| 725 |
int |
| 726 |
v4root_stwr(void) |
| 727 |
{ |
| 728 |
anonarch &= ANON_DEBUG | ANON_VERBOSE; |
| 729 |
anonarch |= ANON_UIDGID | ANON_INODES; |
| 730 |
return (crc_stwr()); |
| 731 |
} |
| 732 |
|
| 733 |
int |
| 734 |
v4norm_stwr(void) |
| 735 |
{ |
| 736 |
anonarch &= ANON_DEBUG | ANON_VERBOSE; |
| 737 |
anonarch |= ANON_UIDGID | ANON_INODES | ANON_MTIME | ANON_HARDLINKS; |
| 738 |
return (crc_stwr()); |
| 739 |
} |
| 740 |
|
| 741 |
/* |
| 742 |
* vcpio_wr() |
| 743 |
* copy the data in the ARCHD to buffer in system VR4 cpio |
| 744 |
* (with/without crc) format. |
| 745 |
* Return |
| 746 |
* 0 if file has data to be written after the header, 1 if file has |
| 747 |
* NO data to write after the header, -1 if archive write failed |
| 748 |
*/ |
| 749 |
|
| 750 |
int |
| 751 |
vcpio_wr(ARCHD *arcn) |
| 752 |
{ |
| 753 |
HD_VCPIO *hd; |
| 754 |
unsigned int nsz; |
| 755 |
char hdblk[sizeof(HD_VCPIO)]; |
| 756 |
|
| 757 |
u_long t_uid, t_gid, t_mtime, t_major, t_minor; |
| 758 |
ino_t t_ino; |
| 759 |
|
| 760 |
anonarch_init(); |
| 761 |
|
| 762 |
/* |
| 763 |
* check and repair truncated device and inode fields in the cpio |
| 764 |
* header |
| 765 |
*/ |
| 766 |
if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0) |
| 767 |
return(-1); |
| 768 |
nsz = arcn->nlen + 1; |
| 769 |
hd = (HD_VCPIO *)hdblk; |
| 770 |
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) |
| 771 |
arcn->sb.st_rdev = 0; |
| 772 |
|
| 773 |
/* |
| 774 |
* add the proper magic value depending whether we were asked for |
| 775 |
* file data crc's, and the crc if needed. |
| 776 |
*/ |
| 777 |
if (docrc) { |
| 778 |
if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), |
| 779 |
OCT) || |
| 780 |
ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), |
| 781 |
HEX)) |
| 782 |
goto out; |
| 783 |
} else { |
| 784 |
if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), |
| 785 |
OCT) || |
| 786 |
ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) |
| 787 |
goto out; |
| 788 |
} |
| 789 |
|
| 790 |
t_uid = (anonarch & ANON_UIDGID) ? 0UL : (u_long)arcn->sb.st_uid; |
| 791 |
t_gid = (anonarch & ANON_UIDGID) ? 0UL : (u_long)arcn->sb.st_gid; |
| 792 |
t_mtime = (anonarch & ANON_MTIME) ? 0UL : (u_long)arcn->sb.st_mtime; |
| 793 |
t_ino = (anonarch & ANON_INODES) ? (ino_t)chk_flnk(arcn) : |
| 794 |
arcn->sb.st_ino; |
| 795 |
t_major = (anonarch & ANON_INODES) ? 0UL : (u_long)MAJOR(arcn->sb.st_dev); |
| 796 |
t_minor = (anonarch & ANON_INODES) ? 0UL : (u_long)MINOR(arcn->sb.st_dev); |
| 797 |
if (!cpio_trail(arcn, NULL, 0, NULL)) |
| 798 |
t_ino = 0UL; |
| 799 |
if (t_ino == (ino_t)-1) { |
| 800 |
paxwarn(1, "Invalid inode number for file %s", arcn->org_name); |
| 801 |
return (1); |
| 802 |
} |
| 803 |
if (!(anonarch & ANON_HARDLINKS)) |
| 804 |
arcn->type &= ~PAX_LINKOR; |
| 805 |
|
| 806 |
switch (arcn->type) { |
| 807 |
case PAX_CTG: |
| 808 |
case PAX_REG: |
| 809 |
case PAX_HRG: |
| 810 |
/* |
| 811 |
* caller will copy file data to the archive. tell him how |
| 812 |
* much to pad. |
| 813 |
*/ |
| 814 |
arcn->pad = VCPIO_PAD(arcn->sb.st_size); |
| 815 |
# ifdef LONG_OFF_T |
| 816 |
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, |
| 817 |
sizeof(hd->c_filesize), HEX)) { |
| 818 |
# else |
| 819 |
if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, |
| 820 |
sizeof(hd->c_filesize), HEX)) { |
| 821 |
# endif |
| 822 |
paxwarn(1,"File is too large for sv4cpio format %s", |
| 823 |
arcn->org_name); |
| 824 |
return(1); |
| 825 |
} |
| 826 |
break; |
| 827 |
case PAX_SLK: |
| 828 |
/* |
| 829 |
* no file data for the caller to process, the file data has |
| 830 |
* the size of the link |
| 831 |
*/ |
| 832 |
arcn->pad = 0L; |
| 833 |
if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, |
| 834 |
sizeof(hd->c_filesize), HEX)) |
| 835 |
goto out; |
| 836 |
break; |
| 837 |
default: |
| 838 |
/* |
| 839 |
* no file data for the caller to process |
| 840 |
*/ |
| 841 |
arcn->pad = 0L; |
| 842 |
if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), |
| 843 |
HEX)) |
| 844 |
goto out; |
| 845 |
break; |
| 846 |
} |
| 847 |
|
| 848 |
if (anonarch & ANON_DEBUG) |
| 849 |
paxwarn(0, "writing dev %lX:%lx inode %10lX mode %8lo user %ld:%ld" |
| 850 |
"\n\tnlink %3ld mtime %08lX name '%s'", t_major, t_minor, |
| 851 |
(u_long)t_ino, (u_long)arcn->sb.st_mode, t_uid, t_gid, |
| 852 |
(u_long)arcn->sb.st_nlink, t_mtime, arcn->name); |
| 853 |
|
| 854 |
/* |
| 855 |
* set the other fields in the header |
| 856 |
*/ |
| 857 |
if (ul_asc((u_long)t_ino, hd->c_ino, sizeof(hd->c_ino), |
| 858 |
HEX) || |
| 859 |
ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), |
| 860 |
HEX) || |
| 861 |
ul_asc(t_uid, hd->c_uid, sizeof(hd->c_uid), |
| 862 |
HEX) || |
| 863 |
ul_asc(t_gid, hd->c_gid, sizeof(hd->c_gid), |
| 864 |
HEX) || |
| 865 |
ul_asc(t_mtime, hd->c_mtime, sizeof(hd->c_mtime), |
| 866 |
HEX) || |
| 867 |
ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), |
| 868 |
HEX) || |
| 869 |
/* device major:minor of the device the file resides on */ |
| 870 |
ul_asc(t_major, hd->c_maj, sizeof(hd->c_maj), HEX) || |
| 871 |
ul_asc(t_minor, hd->c_min, sizeof(hd->c_min), HEX) || |
| 872 |
/* device major:minor of the file if it's a device node */ |
| 873 |
ul_asc((u_long)MAJOR(arcn->sb.st_rdev), hd->c_rmaj, |
| 874 |
sizeof(hd->c_rmaj), HEX) || |
| 875 |
ul_asc((u_long)MINOR(arcn->sb.st_rdev), hd->c_rmin, |
| 876 |
sizeof(hd->c_rmin), HEX) || |
| 877 |
ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) |
| 878 |
goto out; |
| 879 |
|
| 880 |
/* |
| 881 |
* write the header, the file name and padding as required. |
| 882 |
*/ |
| 883 |
if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) || |
| 884 |
(wr_rdbuf(arcn->name, (int)nsz) < 0) || |
| 885 |
(wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) { |
| 886 |
paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name); |
| 887 |
return(-1); |
| 888 |
} |
| 889 |
|
| 890 |
/* |
| 891 |
* if we have file data, tell the caller we are done, copy the file |
| 892 |
*/ |
| 893 |
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || |
| 894 |
(arcn->type == PAX_HRG)) |
| 895 |
return(0); |
| 896 |
|
| 897 |
/* |
| 898 |
* if we are a detected hard link, we're done too, but no data written |
| 899 |
*/ |
| 900 |
if (arcn->type & PAX_LINKOR) { |
| 901 |
arcn->type &= ~PAX_LINKOR; |
| 902 |
return (1); |
| 903 |
} |
| 904 |
|
| 905 |
/* |
| 906 |
* if we are not a link, tell the caller we are done, go to next file |
| 907 |
*/ |
| 908 |
if (arcn->type != PAX_SLK) |
| 909 |
return(1); |
| 910 |
|
| 911 |
/* |
| 912 |
* write the link name, tell the caller we are done. |
| 913 |
*/ |
| 914 |
if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || |
| 915 |
(wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) { |
| 916 |
paxwarn(1,"Could not write sv4cpio link name for %s", |
| 917 |
arcn->org_name); |
| 918 |
return(-1); |
| 919 |
} |
| 920 |
return(1); |
| 921 |
|
| 922 |
out: |
| 923 |
/* |
| 924 |
* header field is out of range |
| 925 |
*/ |
| 926 |
paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name); |
| 927 |
return(1); |
| 928 |
} |
| 929 |
|
| 930 |
/* |
| 931 |
* Routines common to the old binary header cpio |
| 932 |
*/ |
| 933 |
|
| 934 |
/* |
| 935 |
* bcpio_id() |
| 936 |
* determine if a block given to us is a old binary cpio header |
| 937 |
* (with/without header byte swapping) |
| 938 |
* Return: |
| 939 |
* 0 if a valid header, -1 otherwise |
| 940 |
*/ |
| 941 |
|
| 942 |
int |
| 943 |
bcpio_id(char *blk, int size) |
| 944 |
{ |
| 945 |
if ((size_t)size < sizeof(HD_BCPIO)) |
| 946 |
return(-1); |
| 947 |
|
| 948 |
/* |
| 949 |
* check both normal and byte swapped magic cookies |
| 950 |
*/ |
| 951 |
if (((u_short)SHRT_EXT(blk)) == MAGIC) |
| 952 |
return(0); |
| 953 |
if (((u_short)RSHRT_EXT(blk)) == MAGIC) { |
| 954 |
if (!swp_head) |
| 955 |
++swp_head; |
| 956 |
return(0); |
| 957 |
} |
| 958 |
return(-1); |
| 959 |
} |
| 960 |
|
| 961 |
/* |
| 962 |
* bcpio_rd() |
| 963 |
* determine if a buffer is a old binary archive entry. (it may have byte |
| 964 |
* swapped header) convert and store the values in the ARCHD parameter. |
| 965 |
* This is a very old header format and should not really be used. |
| 966 |
* Return: |
| 967 |
* 0 if a valid header, -1 otherwise. |
| 968 |
*/ |
| 969 |
|
| 970 |
int |
| 971 |
bcpio_rd(ARCHD *arcn, char *buf) |
| 972 |
{ |
| 973 |
HD_BCPIO *hd; |
| 974 |
int nsz; |
| 975 |
|
| 976 |
/* |
| 977 |
* check the header |
| 978 |
*/ |
| 979 |
if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0) |
| 980 |
return(-1); |
| 981 |
|
| 982 |
arcn->pad = 0L; |
| 983 |
hd = (HD_BCPIO *)buf; |
| 984 |
if (swp_head) { |
| 985 |
/* |
| 986 |
* header has swapped bytes on 16 bit boundaries |
| 987 |
*/ |
| 988 |
arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev)); |
| 989 |
arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino)); |
| 990 |
arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode)); |
| 991 |
arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid)); |
| 992 |
arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid)); |
| 993 |
arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink)); |
| 994 |
arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev)); |
| 995 |
arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1)); |
| 996 |
arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | |
| 997 |
((time_t)(RSHRT_EXT(hd->h_mtime_2))); |
| 998 |
arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1)); |
| 999 |
arcn->sb.st_size = (arcn->sb.st_size << 16) | |
| 1000 |
((off_t)(RSHRT_EXT(hd->h_filesize_2))); |
| 1001 |
nsz = (int)(RSHRT_EXT(hd->h_namesize)); |
| 1002 |
} else { |
| 1003 |
arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev)); |
| 1004 |
arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino)); |
| 1005 |
arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode)); |
| 1006 |
arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid)); |
| 1007 |
arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid)); |
| 1008 |
arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink)); |
| 1009 |
arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev)); |
| 1010 |
arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1)); |
| 1011 |
arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | |
| 1012 |
((time_t)(SHRT_EXT(hd->h_mtime_2))); |
| 1013 |
arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1)); |
| 1014 |
arcn->sb.st_size = (arcn->sb.st_size << 16) | |
| 1015 |
((off_t)(SHRT_EXT(hd->h_filesize_2))); |
| 1016 |
nsz = (int)(SHRT_EXT(hd->h_namesize)); |
| 1017 |
} |
| 1018 |
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; |
| 1019 |
|
| 1020 |
/* |
| 1021 |
* check the file name size, if bogus give up. otherwise read the file |
| 1022 |
* name |
| 1023 |
*/ |
| 1024 |
if (nsz < 2) |
| 1025 |
return(-1); |
| 1026 |
arcn->nlen = nsz - 1; |
| 1027 |
if (rd_nm(arcn, nsz) < 0) |
| 1028 |
return(-1); |
| 1029 |
|
| 1030 |
/* |
| 1031 |
* header + file name are aligned to 2 byte boundaries, skip if needed |
| 1032 |
*/ |
| 1033 |
if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0) |
| 1034 |
return(-1); |
| 1035 |
|
| 1036 |
/* |
| 1037 |
* if not a link (or a file with no data), calculate pad size (for |
| 1038 |
* padding which follows the file data), clear the link name and return |
| 1039 |
*/ |
| 1040 |
if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){ |
| 1041 |
/* |
| 1042 |
* we have a valid header (not a link) |
| 1043 |
*/ |
| 1044 |
arcn->ln_nlen = 0; |
| 1045 |
arcn->ln_name[0] = '\0'; |
| 1046 |
arcn->pad = BCPIO_PAD(arcn->sb.st_size); |
| 1047 |
return(com_rd(arcn)); |
| 1048 |
} |
| 1049 |
|
| 1050 |
if ((rd_ln_nm(arcn) < 0) || |
| 1051 |
(rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0)) |
| 1052 |
return(-1); |
| 1053 |
|
| 1054 |
/* |
| 1055 |
* we have a valid header (with a link) |
| 1056 |
*/ |
| 1057 |
return(com_rd(arcn)); |
| 1058 |
} |
| 1059 |
|
| 1060 |
/* |
| 1061 |
* bcpio_endrd() |
| 1062 |
* no cleanup needed here, just return size of the trailer (for append) |
| 1063 |
* Return: |
| 1064 |
* size of trailer header in this format |
| 1065 |
*/ |
| 1066 |
|
| 1067 |
off_t |
| 1068 |
bcpio_endrd(void) |
| 1069 |
{ |
| 1070 |
return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) + |
| 1071 |
(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))))); |
| 1072 |
} |
| 1073 |
|
| 1074 |
/* |
| 1075 |
* bcpio_wr() |
| 1076 |
* copy the data in the ARCHD to buffer in old binary cpio format |
| 1077 |
* There is a real chance of field overflow with this critter. So we |
| 1078 |
* always check the conversion is ok. nobody in their right mind |
| 1079 |
* should write an archive in this format... |
| 1080 |
* Return |
| 1081 |
* 0 if file has data to be written after the header, 1 if file has NO |
| 1082 |
* data to write after the header, -1 if archive write failed |
| 1083 |
*/ |
| 1084 |
|
| 1085 |
int |
| 1086 |
bcpio_wr(ARCHD *arcn) |
| 1087 |
{ |
| 1088 |
HD_BCPIO *hd; |
| 1089 |
int nsz; |
| 1090 |
char hdblk[sizeof(HD_BCPIO)]; |
| 1091 |
off_t t_offt; |
| 1092 |
int t_int; |
| 1093 |
time_t t_timet; |
| 1094 |
|
| 1095 |
/* |
| 1096 |
* check and repair truncated device and inode fields in the cpio |
| 1097 |
* header |
| 1098 |
*/ |
| 1099 |
if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0) |
| 1100 |
return(-1); |
| 1101 |
|
| 1102 |
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) |
| 1103 |
arcn->sb.st_rdev = 0; |
| 1104 |
hd = (HD_BCPIO *)hdblk; |
| 1105 |
|
| 1106 |
switch (arcn->type) { |
| 1107 |
case PAX_CTG: |
| 1108 |
case PAX_REG: |
| 1109 |
case PAX_HRG: |
| 1110 |
/* |
| 1111 |
* caller will copy file data to the archive. tell him how |
| 1112 |
* much to pad. |
| 1113 |
*/ |
| 1114 |
arcn->pad = BCPIO_PAD(arcn->sb.st_size); |
| 1115 |
hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size); |
| 1116 |
hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size); |
| 1117 |
hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size); |
| 1118 |
hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size); |
| 1119 |
t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1)); |
| 1120 |
t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2))); |
| 1121 |
if (arcn->sb.st_size != t_offt) { |
| 1122 |
paxwarn(1,"File is too large for bcpio format %s", |
| 1123 |
arcn->org_name); |
| 1124 |
return(1); |
| 1125 |
} |
| 1126 |
break; |
| 1127 |
case PAX_SLK: |
| 1128 |
/* |
| 1129 |
* no file data for the caller to process, the file data has |
| 1130 |
* the size of the link |
| 1131 |
*/ |
| 1132 |
arcn->pad = 0L; |
| 1133 |
hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen); |
| 1134 |
hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen); |
| 1135 |
hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen); |
| 1136 |
hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen); |
| 1137 |
t_int = (int)(SHRT_EXT(hd->h_filesize_1)); |
| 1138 |
t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2))); |
| 1139 |
if (arcn->ln_nlen != t_int) |
| 1140 |
goto out; |
| 1141 |
break; |
| 1142 |
default: |
| 1143 |
/* |
| 1144 |
* no file data for the caller to process |
| 1145 |
*/ |
| 1146 |
arcn->pad = 0L; |
| 1147 |
hd->h_filesize_1[0] = (char)0; |
| 1148 |
hd->h_filesize_1[1] = (char)0; |
| 1149 |
hd->h_filesize_2[0] = (char)0; |
| 1150 |
hd->h_filesize_2[1] = (char)0; |
| 1151 |
break; |
| 1152 |
} |
| 1153 |
|
| 1154 |
/* |
| 1155 |
* build up the rest of the fields |
| 1156 |
*/ |
| 1157 |
hd->h_magic[0] = CHR_WR_2(MAGIC); |
| 1158 |
hd->h_magic[1] = CHR_WR_3(MAGIC); |
| 1159 |
hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev); |
| 1160 |
hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev); |
| 1161 |
if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev))) |
| 1162 |
goto out; |
| 1163 |
hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino); |
| 1164 |
hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino); |
| 1165 |
if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino))) |
| 1166 |
goto out; |
| 1167 |
hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode); |
| 1168 |
hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode); |
| 1169 |
if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode))) |
| 1170 |
goto out; |
| 1171 |
hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid); |
| 1172 |
hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid); |
| 1173 |
if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid))) |
| 1174 |
goto out; |
| 1175 |
hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid); |
| 1176 |
hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid); |
| 1177 |
if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid))) |
| 1178 |
goto out; |
| 1179 |
hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink); |
| 1180 |
hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink); |
| 1181 |
if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink))) |
| 1182 |
goto out; |
| 1183 |
hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev); |
| 1184 |
hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev); |
| 1185 |
if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev))) |
| 1186 |
goto out; |
| 1187 |
hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime); |
| 1188 |
hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime); |
| 1189 |
hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime); |
| 1190 |
hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime); |
| 1191 |
t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1)); |
| 1192 |
t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2))); |
| 1193 |
if (arcn->sb.st_mtime != t_timet) |
| 1194 |
goto out; |
| 1195 |
nsz = arcn->nlen + 1; |
| 1196 |
hd->h_namesize[0] = CHR_WR_2(nsz); |
| 1197 |
hd->h_namesize[1] = CHR_WR_3(nsz); |
| 1198 |
if (nsz != (int)(SHRT_EXT(hd->h_namesize))) |
| 1199 |
goto out; |
| 1200 |
|
| 1201 |
/* |
| 1202 |
* write the header, the file name and padding as required. |
| 1203 |
*/ |
| 1204 |
if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) || |
| 1205 |
(wr_rdbuf(arcn->name, nsz) < 0) || |
| 1206 |
(wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) { |
| 1207 |
paxwarn(1, "Could not write bcpio header for %s", arcn->org_name); |
| 1208 |
return(-1); |
| 1209 |
} |
| 1210 |
|
| 1211 |
/* |
| 1212 |
* if we have file data, tell the caller we are done |
| 1213 |
*/ |
| 1214 |
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || |
| 1215 |
(arcn->type == PAX_HRG)) |
| 1216 |
return(0); |
| 1217 |
|
| 1218 |
/* |
| 1219 |
* if we are not a link, tell the caller we are done, go to next file |
| 1220 |
*/ |
| 1221 |
if (arcn->type != PAX_SLK) |
| 1222 |
return(1); |
| 1223 |
|
| 1224 |
/* |
| 1225 |
* write the link name, tell the caller we are done. |
| 1226 |
*/ |
| 1227 |
if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || |
| 1228 |
(wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) { |
| 1229 |
paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name); |
| 1230 |
return(-1); |
| 1231 |
} |
| 1232 |
return(1); |
| 1233 |
|
| 1234 |
out: |
| 1235 |
/* |
| 1236 |
* header field is out of range |
| 1237 |
*/ |
| 1238 |
paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name); |
| 1239 |
return(1); |
| 1240 |
} |