| 1 |
/** $MirOS: src/bin/pax/ar_io.c,v 1.8 2007/02/17 04:52:39 tg Exp $ */ |
| 2 |
/* $OpenBSD: ar_io.c,v 1.37 2005/08/04 10:02:44 mpf Exp $ */ |
| 3 |
/* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */ |
| 4 |
|
| 5 |
/*- |
| 6 |
* Copyright (c) 1992 Keith Muller. |
| 7 |
* Copyright (c) 1992, 1993 |
| 8 |
* The Regents of the University of California. All rights reserved. |
| 9 |
* |
| 10 |
* This code is derived from software contributed to Berkeley by |
| 11 |
* Keith Muller of the University of California, San Diego. |
| 12 |
* |
| 13 |
* Redistribution and use in source and binary forms, with or without |
| 14 |
* modification, are permitted provided that the following conditions |
| 15 |
* are met: |
| 16 |
* 1. Redistributions of source code must retain the above copyright |
| 17 |
* notice, this list of conditions and the following disclaimer. |
| 18 |
* 2. Redistributions in binary form must reproduce the above copyright |
| 19 |
* notice, this list of conditions and the following disclaimer in the |
| 20 |
* documentation and/or other materials provided with the distribution. |
| 21 |
* 3. Neither the name of the University nor the names of its contributors |
| 22 |
* may be used to endorse or promote products derived from this software |
| 23 |
* without specific prior written permission. |
| 24 |
* |
| 25 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 26 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 27 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 28 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 29 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 30 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 31 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 32 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 33 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 34 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 35 |
* SUCH DAMAGE. |
| 36 |
*/ |
| 37 |
|
| 38 |
#include <sys/param.h> |
| 39 |
#include <sys/time.h> |
| 40 |
#include <sys/stat.h> |
| 41 |
#include <sys/ioctl.h> |
| 42 |
#ifndef __INTERIX |
| 43 |
#include <sys/mtio.h> |
| 44 |
#endif |
| 45 |
#include <sys/wait.h> |
| 46 |
#include <signal.h> |
| 47 |
#include <string.h> |
| 48 |
#include <fcntl.h> |
| 49 |
#include <unistd.h> |
| 50 |
#include <stdio.h> |
| 51 |
#include <errno.h> |
| 52 |
#include <stdlib.h> |
| 53 |
#include <err.h> |
| 54 |
#include "pax.h" |
| 55 |
#include "options.h" |
| 56 |
#include "extern.h" |
| 57 |
|
| 58 |
__SCCSID("@(#)ar_io.c 8.2 (Berkeley) 4/18/94"); |
| 59 |
__RCSID("$MirOS: src/bin/pax/ar_io.c,v 1.8 2007/02/17 04:52:39 tg Exp $"); |
| 60 |
|
| 61 |
/* |
| 62 |
* Routines which deal directly with the archive I/O device/file. |
| 63 |
*/ |
| 64 |
|
| 65 |
#define DMOD 0666 /* default mode of created archives */ |
| 66 |
#define EXT_MODE O_RDONLY /* open mode for list/extract */ |
| 67 |
#define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */ |
| 68 |
#define APP_MODE O_RDWR /* mode for append */ |
| 69 |
#define STDO "<STDOUT>" /* pseudo name for stdout */ |
| 70 |
#define STDN "<STDIN>" /* pseudo name for stdin */ |
| 71 |
static int arfd = -1; /* archive file descriptor */ |
| 72 |
static int artyp = ISREG; /* archive type: file/FIFO/tape */ |
| 73 |
static int arvol = 1; /* archive volume number */ |
| 74 |
static int lstrval = -1; /* return value from last i/o */ |
| 75 |
static int io_ok; /* i/o worked on volume after resync */ |
| 76 |
static int did_io; /* did i/o ever occur on volume? */ |
| 77 |
static int done; /* set via tty termination */ |
| 78 |
static struct stat arsb; /* stat of archive device at open */ |
| 79 |
static int invld_rec; /* tape has out of spec record size */ |
| 80 |
static int wr_trail = 1; /* trailer was rewritten in append */ |
| 81 |
static int can_unlnk = 0; /* do we unlink null archives? */ |
| 82 |
const char *arcname; /* printable name of archive */ |
| 83 |
static char *arcname_; /* this is so we can free(3) it */ |
| 84 |
const char *gzip_program; /* name of gzip program */ |
| 85 |
static pid_t zpid = -1; /* pid of child process */ |
| 86 |
int force_one_volume; /* 1 if we ignore volume changes */ |
| 87 |
|
| 88 |
#ifndef __INTERIX |
| 89 |
static int get_phys(void); |
| 90 |
#endif |
| 91 |
extern sigset_t s_mask; |
| 92 |
static void ar_start_gzip(int, int); |
| 93 |
|
| 94 |
/* |
| 95 |
* ar_open() |
| 96 |
* Opens the next archive volume. Determines the type of the device and |
| 97 |
* sets up block sizes as required by the archive device and the format. |
| 98 |
* Note: we may be called with name == NULL on the first open only. |
| 99 |
* Return: |
| 100 |
* -1 on failure, 0 otherwise |
| 101 |
*/ |
| 102 |
|
| 103 |
int |
| 104 |
ar_open(const char *name) |
| 105 |
{ |
| 106 |
#ifndef __INTERIX |
| 107 |
struct mtget mb; |
| 108 |
#endif |
| 109 |
|
| 110 |
if (arfd != -1) |
| 111 |
(void)close(arfd); |
| 112 |
arfd = -1; |
| 113 |
can_unlnk = did_io = io_ok = invld_rec = 0; |
| 114 |
artyp = ISREG; |
| 115 |
flcnt = 0; |
| 116 |
|
| 117 |
/* |
| 118 |
* open based on overall operation mode |
| 119 |
*/ |
| 120 |
switch (act) { |
| 121 |
case LIST: |
| 122 |
case EXTRACT: |
| 123 |
if (name == NULL) { |
| 124 |
arfd = STDIN_FILENO; |
| 125 |
arcname = STDN; |
| 126 |
} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) |
| 127 |
syswarn(1, errno, "Failed open to read on %s", name); |
| 128 |
if (arfd != -1 && gzip_program != NULL) |
| 129 |
ar_start_gzip(arfd, 0); |
| 130 |
break; |
| 131 |
case ARCHIVE: |
| 132 |
if (name == NULL) { |
| 133 |
arfd = STDOUT_FILENO; |
| 134 |
arcname = STDO; |
| 135 |
} else if ((arfd = open(name, AR_MODE, DMOD)) < 0) |
| 136 |
syswarn(1, errno, "Failed open to write on %s", name); |
| 137 |
else |
| 138 |
can_unlnk = 1; |
| 139 |
if (arfd != -1 && gzip_program != NULL) |
| 140 |
ar_start_gzip(arfd, 1); |
| 141 |
break; |
| 142 |
case APPND: |
| 143 |
if (name == NULL) { |
| 144 |
arfd = STDOUT_FILENO; |
| 145 |
arcname = STDO; |
| 146 |
} else if ((arfd = open(name, APP_MODE, DMOD)) < 0) |
| 147 |
syswarn(1, errno, "Failed open to read/write on %s", |
| 148 |
name); |
| 149 |
break; |
| 150 |
case COPY: |
| 151 |
/* |
| 152 |
* arfd not used in COPY mode |
| 153 |
*/ |
| 154 |
arcname = "<NONE>"; |
| 155 |
lstrval = 1; |
| 156 |
return(0); |
| 157 |
} |
| 158 |
if (arfd < 0) |
| 159 |
return(-1); |
| 160 |
|
| 161 |
if (chdname != NULL) |
| 162 |
if (chdir(chdname) != 0) { |
| 163 |
syswarn(1, errno, "Failed chdir to %s", chdname); |
| 164 |
return(-1); |
| 165 |
} |
| 166 |
/* |
| 167 |
* set up is based on device type |
| 168 |
*/ |
| 169 |
if (fstat(arfd, &arsb) < 0) { |
| 170 |
syswarn(1, errno, "Failed stat on %s", arcname); |
| 171 |
(void)close(arfd); |
| 172 |
arfd = -1; |
| 173 |
can_unlnk = 0; |
| 174 |
return(-1); |
| 175 |
} |
| 176 |
if (S_ISDIR(arsb.st_mode)) { |
| 177 |
paxwarn(0, "Cannot write an archive on top of a directory %s", |
| 178 |
arcname); |
| 179 |
(void)close(arfd); |
| 180 |
arfd = -1; |
| 181 |
can_unlnk = 0; |
| 182 |
return(-1); |
| 183 |
} |
| 184 |
|
| 185 |
if (S_ISCHR(arsb.st_mode)) |
| 186 |
#ifndef __INTERIX |
| 187 |
artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; |
| 188 |
#else |
| 189 |
artyp = ISCHR; |
| 190 |
#endif |
| 191 |
else if (S_ISBLK(arsb.st_mode)) |
| 192 |
artyp = ISBLK; |
| 193 |
else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) |
| 194 |
artyp = ISPIPE; |
| 195 |
else |
| 196 |
artyp = ISREG; |
| 197 |
|
| 198 |
/* |
| 199 |
* make sure we beyond any doubt that we only can unlink regular files |
| 200 |
* we created |
| 201 |
*/ |
| 202 |
if (artyp != ISREG) |
| 203 |
can_unlnk = 0; |
| 204 |
/* |
| 205 |
* if we are writing, we are done |
| 206 |
*/ |
| 207 |
if (act == ARCHIVE) { |
| 208 |
blksz = rdblksz = wrblksz; |
| 209 |
lstrval = 1; |
| 210 |
return(0); |
| 211 |
} |
| 212 |
|
| 213 |
/* |
| 214 |
* set default blksz on read. APPNDs writes rdblksz on the last volume |
| 215 |
* On all new archive volumes, we shift to wrblksz (if the user |
| 216 |
* specified one, otherwise we will continue to use rdblksz). We |
| 217 |
* must set blocksize based on what kind of device the archive is |
| 218 |
* stored. |
| 219 |
*/ |
| 220 |
switch (artyp) { |
| 221 |
case ISTAPE: |
| 222 |
/* |
| 223 |
* Tape drives come in at least two flavors. Those that support |
| 224 |
* variable sized records and those that have fixed sized |
| 225 |
* records. They must be treated differently. For tape drives |
| 226 |
* that support variable sized records, we must make large |
| 227 |
* reads to make sure we get the entire record, otherwise we |
| 228 |
* will just get the first part of the record (up to size we |
| 229 |
* asked). Tapes with fixed sized records may or may not return |
| 230 |
* multiple records in a single read. We really do not care |
| 231 |
* what the physical record size is UNLESS we are going to |
| 232 |
* append. (We will need the physical block size to rewrite |
| 233 |
* the trailer). Only when we are appending do we go to the |
| 234 |
* effort to figure out the true PHYSICAL record size. |
| 235 |
*/ |
| 236 |
blksz = rdblksz = MAXBLK; |
| 237 |
break; |
| 238 |
case ISPIPE: |
| 239 |
case ISBLK: |
| 240 |
case ISCHR: |
| 241 |
/* |
| 242 |
* Blocksize is not a major issue with these devices (but must |
| 243 |
* be kept a multiple of 512). If the user specified a write |
| 244 |
* block size, we use that to read. Under append, we must |
| 245 |
* always keep blksz == rdblksz. Otherwise we go ahead and use |
| 246 |
* the device optimal blocksize as (and if) returned by stat |
| 247 |
* and if it is within pax specs. |
| 248 |
*/ |
| 249 |
if ((act == APPND) && wrblksz) { |
| 250 |
blksz = rdblksz = wrblksz; |
| 251 |
break; |
| 252 |
} |
| 253 |
|
| 254 |
if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && |
| 255 |
((arsb.st_blksize % BLKMULT) == 0)) |
| 256 |
rdblksz = arsb.st_blksize; |
| 257 |
else |
| 258 |
rdblksz = DEVBLK; |
| 259 |
/* |
| 260 |
* For performance go for large reads when we can without harm |
| 261 |
*/ |
| 262 |
if ((act == APPND) || (artyp == ISCHR)) |
| 263 |
blksz = rdblksz; |
| 264 |
else |
| 265 |
blksz = MAXBLK; |
| 266 |
break; |
| 267 |
case ISREG: |
| 268 |
/* |
| 269 |
* if the user specified wrblksz works, use it. Under appends |
| 270 |
* we must always keep blksz == rdblksz |
| 271 |
*/ |
| 272 |
if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ |
| 273 |
blksz = rdblksz = wrblksz; |
| 274 |
break; |
| 275 |
} |
| 276 |
/* |
| 277 |
* See if we can find the blocking factor from the file size |
| 278 |
*/ |
| 279 |
for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) |
| 280 |
if ((arsb.st_size % rdblksz) == 0) |
| 281 |
break; |
| 282 |
/* |
| 283 |
* When we cannot find a match, we may have a flawed archive. |
| 284 |
*/ |
| 285 |
if (rdblksz <= 0) |
| 286 |
rdblksz = FILEBLK; |
| 287 |
/* |
| 288 |
* for performance go for large reads when we can |
| 289 |
*/ |
| 290 |
if (act == APPND) |
| 291 |
blksz = rdblksz; |
| 292 |
else |
| 293 |
blksz = MAXBLK; |
| 294 |
break; |
| 295 |
default: |
| 296 |
/* |
| 297 |
* should never happen, worst case, slow... |
| 298 |
*/ |
| 299 |
blksz = rdblksz = BLKMULT; |
| 300 |
break; |
| 301 |
} |
| 302 |
lstrval = 1; |
| 303 |
return(0); |
| 304 |
} |
| 305 |
|
| 306 |
/* |
| 307 |
* ar_close() |
| 308 |
* closes archive device, increments volume number, and prints i/o summary |
| 309 |
*/ |
| 310 |
void |
| 311 |
ar_close(void) |
| 312 |
{ |
| 313 |
int status; |
| 314 |
|
| 315 |
if (arfd < 0) { |
| 316 |
did_io = io_ok = flcnt = 0; |
| 317 |
return; |
| 318 |
} |
| 319 |
|
| 320 |
/* |
| 321 |
* Close archive file. This may take a LONG while on tapes (we may be |
| 322 |
* forced to wait for the rewind to complete) so tell the user what is |
| 323 |
* going on (this avoids the user hitting control-c thinking pax is |
| 324 |
* broken). |
| 325 |
*/ |
| 326 |
if (vflag && (artyp == ISTAPE)) { |
| 327 |
if (vfpart) |
| 328 |
(void)putc('\n', listf); |
| 329 |
(void)fprintf(listf, |
| 330 |
"%s: Waiting for tape drive close to complete...", |
| 331 |
argv0); |
| 332 |
(void)fflush(listf); |
| 333 |
} |
| 334 |
|
| 335 |
/* |
| 336 |
* if nothing was written to the archive (and we created it), we remove |
| 337 |
* it |
| 338 |
*/ |
| 339 |
if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && |
| 340 |
(arsb.st_size == 0)) { |
| 341 |
(void)unlink(arcname); |
| 342 |
can_unlnk = 0; |
| 343 |
} |
| 344 |
|
| 345 |
/* |
| 346 |
* for a quick extract/list, pax frequently exits before the child |
| 347 |
* process is done |
| 348 |
*/ |
| 349 |
if ((act == LIST || act == EXTRACT) && nflag && zpid > 0) |
| 350 |
kill(zpid, SIGINT); |
| 351 |
|
| 352 |
(void)close(arfd); |
| 353 |
|
| 354 |
/* Do not exit before child to ensure data integrity */ |
| 355 |
if (zpid > 0) |
| 356 |
waitpid(zpid, &status, 0); |
| 357 |
|
| 358 |
if (vflag && (artyp == ISTAPE)) { |
| 359 |
(void)fputs("done.\n", listf); |
| 360 |
vfpart = 0; |
| 361 |
(void)fflush(listf); |
| 362 |
} |
| 363 |
arfd = -1; |
| 364 |
|
| 365 |
if (!io_ok && !did_io) { |
| 366 |
flcnt = 0; |
| 367 |
return; |
| 368 |
} |
| 369 |
did_io = io_ok = 0; |
| 370 |
|
| 371 |
/* |
| 372 |
* The volume number is only increased when the last device has data |
| 373 |
* and we have already determined the archive format. |
| 374 |
*/ |
| 375 |
if (frmt != NULL) |
| 376 |
++arvol; |
| 377 |
|
| 378 |
if (!vflag) { |
| 379 |
flcnt = 0; |
| 380 |
return; |
| 381 |
} |
| 382 |
|
| 383 |
/* |
| 384 |
* Print out a summary of I/O for this archive volume. |
| 385 |
*/ |
| 386 |
if (vfpart) { |
| 387 |
(void)putc('\n', listf); |
| 388 |
vfpart = 0; |
| 389 |
} |
| 390 |
|
| 391 |
/* |
| 392 |
* If we have not determined the format yet, we just say how many bytes |
| 393 |
* we have skipped over looking for a header to id. there is no way we |
| 394 |
* could have written anything yet. |
| 395 |
*/ |
| 396 |
if (frmt == NULL) { |
| 397 |
# ifdef LONG_OFF_T |
| 398 |
(void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n", |
| 399 |
# else |
| 400 |
(void)fprintf(listf, "%s: unknown format, %llu bytes skipped.\n", |
| 401 |
# endif |
| 402 |
argv0, rdcnt); |
| 403 |
(void)fflush(listf); |
| 404 |
flcnt = 0; |
| 405 |
return; |
| 406 |
} |
| 407 |
|
| 408 |
if (strcmp(NM_CPIO, argv0) == 0) |
| 409 |
# ifdef LONG_OFF_T |
| 410 |
(void)fprintf(listf, "%lu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120); |
| 411 |
# else |
| 412 |
(void)fprintf(listf, "%llu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120); |
| 413 |
# endif |
| 414 |
else if (strcmp(NM_TAR, argv0) != 0) |
| 415 |
(void)fprintf(listf, |
| 416 |
# ifdef LONG_OFF_T |
| 417 |
"%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n", |
| 418 |
# else |
| 419 |
"%s: %s vol %d, %lu files, %llu bytes read, %llu bytes written.\n", |
| 420 |
# endif |
| 421 |
argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt); |
| 422 |
(void)fflush(listf); |
| 423 |
flcnt = 0; |
| 424 |
} |
| 425 |
|
| 426 |
/* |
| 427 |
* ar_drain() |
| 428 |
* drain any archive format independent padding from an archive read |
| 429 |
* from a socket or a pipe. This is to prevent the process on the |
| 430 |
* other side of the pipe from getting a SIGPIPE (pax will stop |
| 431 |
* reading an archive once a format dependent trailer is detected). |
| 432 |
*/ |
| 433 |
void |
| 434 |
ar_drain(void) |
| 435 |
{ |
| 436 |
int res; |
| 437 |
char drbuf[MAXBLK]; |
| 438 |
|
| 439 |
/* |
| 440 |
* we only drain from a pipe/socket. Other devices can be closed |
| 441 |
* without reading up to end of file. We sure hope that pipe is closed |
| 442 |
* on the other side so we will get an EOF. |
| 443 |
*/ |
| 444 |
if ((artyp != ISPIPE) || (lstrval <= 0)) |
| 445 |
return; |
| 446 |
|
| 447 |
/* |
| 448 |
* keep reading until pipe is drained |
| 449 |
*/ |
| 450 |
while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) |
| 451 |
; |
| 452 |
lstrval = res; |
| 453 |
} |
| 454 |
|
| 455 |
/* |
| 456 |
* ar_set_wr() |
| 457 |
* Set up device right before switching from read to write in an append. |
| 458 |
* device dependent code (if required) to do this should be added here. |
| 459 |
* For all archive devices we are already positioned at the place we want |
| 460 |
* to start writing when this routine is called. |
| 461 |
* Return: |
| 462 |
* 0 if all ready to write, -1 otherwise |
| 463 |
*/ |
| 464 |
|
| 465 |
int |
| 466 |
ar_set_wr(void) |
| 467 |
{ |
| 468 |
off_t cpos; |
| 469 |
|
| 470 |
/* |
| 471 |
* we must make sure the trailer is rewritten on append, ar_next() |
| 472 |
* will stop us if the archive containing the trailer was not written |
| 473 |
*/ |
| 474 |
wr_trail = 0; |
| 475 |
|
| 476 |
/* |
| 477 |
* Add any device dependent code as required here |
| 478 |
*/ |
| 479 |
if (artyp != ISREG) |
| 480 |
return(0); |
| 481 |
/* |
| 482 |
* Ok we have an archive in a regular file. If we were rewriting a |
| 483 |
* file, we must get rid of all the stuff after the current offset |
| 484 |
* (it was not written by pax). |
| 485 |
*/ |
| 486 |
if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) || |
| 487 |
(ftruncate(arfd, cpos) < 0)) { |
| 488 |
syswarn(1, errno, "Unable to truncate archive file"); |
| 489 |
return(-1); |
| 490 |
} |
| 491 |
return(0); |
| 492 |
} |
| 493 |
|
| 494 |
/* |
| 495 |
* ar_app_ok() |
| 496 |
* check if the last volume in the archive allows appends. We cannot check |
| 497 |
* this until we are ready to write since there is no spec that says all |
| 498 |
* volumes in a single archive have to be of the same type... |
| 499 |
* Return: |
| 500 |
* 0 if we can append, -1 otherwise. |
| 501 |
*/ |
| 502 |
|
| 503 |
int |
| 504 |
ar_app_ok(void) |
| 505 |
{ |
| 506 |
if (artyp == ISPIPE) { |
| 507 |
paxwarn(1, "Cannot append to an archive obtained from a pipe."); |
| 508 |
return(-1); |
| 509 |
} |
| 510 |
|
| 511 |
if (!invld_rec) |
| 512 |
return(0); |
| 513 |
paxwarn(1,"Cannot append, device record size %d does not support %s spec", |
| 514 |
rdblksz, argv0); |
| 515 |
return(-1); |
| 516 |
} |
| 517 |
|
| 518 |
/* |
| 519 |
* ar_read() |
| 520 |
* read up to a specified number of bytes from the archive into the |
| 521 |
* supplied buffer. When dealing with tapes we may not always be able to |
| 522 |
* read what we want. |
| 523 |
* Return: |
| 524 |
* Number of bytes in buffer. 0 for end of file, -1 for a read error. |
| 525 |
*/ |
| 526 |
|
| 527 |
int |
| 528 |
ar_read(char *buf, int cnt) |
| 529 |
{ |
| 530 |
int res = 0; |
| 531 |
|
| 532 |
/* |
| 533 |
* if last i/o was in error, no more reads until reset or new volume |
| 534 |
*/ |
| 535 |
if (lstrval <= 0) |
| 536 |
return(lstrval); |
| 537 |
|
| 538 |
/* |
| 539 |
* how we read must be based on device type |
| 540 |
*/ |
| 541 |
switch (artyp) { |
| 542 |
case ISTAPE: |
| 543 |
if ((res = read(arfd, buf, cnt)) > 0) { |
| 544 |
/* |
| 545 |
* CAUTION: tape systems may not always return the same |
| 546 |
* sized records so we leave blksz == MAXBLK. The |
| 547 |
* physical record size that a tape drive supports is |
| 548 |
* very hard to determine in a uniform and portable |
| 549 |
* manner. |
| 550 |
*/ |
| 551 |
io_ok = 1; |
| 552 |
if (res != rdblksz) { |
| 553 |
/* |
| 554 |
* Record size changed. If this happens on |
| 555 |
* any record after the first, we probably have |
| 556 |
* a tape drive which has a fixed record size |
| 557 |
* (we are getting multiple records in a single |
| 558 |
* read). Watch out for record blocking that |
| 559 |
* violates pax spec (must be a multiple of |
| 560 |
* BLKMULT). |
| 561 |
*/ |
| 562 |
rdblksz = res; |
| 563 |
if (rdblksz % BLKMULT) |
| 564 |
invld_rec = 1; |
| 565 |
} |
| 566 |
return(res); |
| 567 |
} |
| 568 |
break; |
| 569 |
case ISREG: |
| 570 |
case ISBLK: |
| 571 |
case ISCHR: |
| 572 |
case ISPIPE: |
| 573 |
default: |
| 574 |
/* |
| 575 |
* Files are so easy to deal with. These other things cannot |
| 576 |
* be trusted at all. So when we are dealing with character |
| 577 |
* devices and pipes we just take what they have ready for us |
| 578 |
* and return. Trying to do anything else with them runs the |
| 579 |
* risk of failure. |
| 580 |
*/ |
| 581 |
if ((res = read(arfd, buf, cnt)) > 0) { |
| 582 |
io_ok = 1; |
| 583 |
return(res); |
| 584 |
} |
| 585 |
break; |
| 586 |
} |
| 587 |
|
| 588 |
/* |
| 589 |
* We are in trouble at this point, something is broken... |
| 590 |
*/ |
| 591 |
lstrval = res; |
| 592 |
if (res < 0) |
| 593 |
syswarn(1, errno, "Failed read on archive volume %d", arvol); |
| 594 |
else |
| 595 |
paxwarn(0, "End of archive volume %d reached", arvol); |
| 596 |
return(res); |
| 597 |
} |
| 598 |
|
| 599 |
/* |
| 600 |
* ar_write() |
| 601 |
* Write a specified number of bytes in supplied buffer to the archive |
| 602 |
* device so it appears as a single "block". Deals with errors and tries |
| 603 |
* to recover when faced with short writes. |
| 604 |
* Return: |
| 605 |
* Number of bytes written. 0 indicates end of volume reached and with no |
| 606 |
* flaws (as best that can be detected). A -1 indicates an unrecoverable |
| 607 |
* error in the archive occurred. |
| 608 |
*/ |
| 609 |
|
| 610 |
int |
| 611 |
ar_write(char *buf, int bsz) |
| 612 |
{ |
| 613 |
int res; |
| 614 |
off_t cpos; |
| 615 |
|
| 616 |
/* |
| 617 |
* do not allow pax to create a "bad" archive. Once a write fails on |
| 618 |
* an archive volume prevent further writes to it. |
| 619 |
*/ |
| 620 |
if (lstrval <= 0) |
| 621 |
return(lstrval); |
| 622 |
|
| 623 |
if ((res = write(arfd, buf, bsz)) == bsz) { |
| 624 |
wr_trail = 1; |
| 625 |
io_ok = 1; |
| 626 |
return(bsz); |
| 627 |
} |
| 628 |
/* |
| 629 |
* write broke, see what we can do with it. We try to send any partial |
| 630 |
* writes that may violate pax spec to the next archive volume. |
| 631 |
*/ |
| 632 |
if (res < 0) |
| 633 |
lstrval = res; |
| 634 |
else |
| 635 |
lstrval = 0; |
| 636 |
|
| 637 |
switch (artyp) { |
| 638 |
case ISREG: |
| 639 |
if ((res > 0) && (res % BLKMULT)) { |
| 640 |
/* |
| 641 |
* try to fix up partial writes which are not BLKMULT |
| 642 |
* in size by forcing the runt record to next archive |
| 643 |
* volume |
| 644 |
*/ |
| 645 |
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) |
| 646 |
break; |
| 647 |
cpos -= (off_t)res; |
| 648 |
if (ftruncate(arfd, cpos) < 0) |
| 649 |
break; |
| 650 |
res = lstrval = 0; |
| 651 |
break; |
| 652 |
} |
| 653 |
if (res >= 0) |
| 654 |
break; |
| 655 |
/* |
| 656 |
* if file is out of space, handle it like a return of 0 |
| 657 |
*/ |
| 658 |
if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) |
| 659 |
res = lstrval = 0; |
| 660 |
break; |
| 661 |
case ISTAPE: |
| 662 |
case ISCHR: |
| 663 |
case ISBLK: |
| 664 |
if (res >= 0) |
| 665 |
break; |
| 666 |
if (errno == EACCES) { |
| 667 |
paxwarn(0, "Write failed, archive is write protected."); |
| 668 |
res = lstrval = 0; |
| 669 |
return(0); |
| 670 |
} |
| 671 |
/* |
| 672 |
* see if we reached the end of media, if so force a change to |
| 673 |
* the next volume |
| 674 |
*/ |
| 675 |
if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) |
| 676 |
res = lstrval = 0; |
| 677 |
break; |
| 678 |
case ISPIPE: |
| 679 |
default: |
| 680 |
/* |
| 681 |
* we cannot fix errors to these devices |
| 682 |
*/ |
| 683 |
break; |
| 684 |
} |
| 685 |
|
| 686 |
/* |
| 687 |
* Better tell the user the bad news... |
| 688 |
* if this is a block aligned archive format, we may have a bad archive |
| 689 |
* if the format wants the header to start at a BLKMULT boundary.. While |
| 690 |
* we can deal with the mis-aligned data, it violates spec and other |
| 691 |
* archive readers will likely fail. if the format is not block |
| 692 |
* aligned, the user may be lucky (and the archive is ok). |
| 693 |
*/ |
| 694 |
if (res >= 0) { |
| 695 |
if (res > 0) |
| 696 |
wr_trail = 1; |
| 697 |
io_ok = 1; |
| 698 |
} |
| 699 |
|
| 700 |
/* |
| 701 |
* If we were trying to rewrite the trailer and it didn't work, we |
| 702 |
* must quit right away. |
| 703 |
*/ |
| 704 |
if (!wr_trail && (res <= 0)) { |
| 705 |
paxwarn(1,"Unable to append, trailer re-write failed. Quitting."); |
| 706 |
return(res); |
| 707 |
} |
| 708 |
|
| 709 |
if (res == 0) |
| 710 |
paxwarn(0, "End of archive volume %d reached", arvol); |
| 711 |
else if (res < 0) |
| 712 |
syswarn(1, errno, "Failed write to archive volume: %d", arvol); |
| 713 |
else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0)) |
| 714 |
paxwarn(0,"WARNING: partial archive write. Archive MAY BE FLAWED"); |
| 715 |
else |
| 716 |
paxwarn(1,"WARNING: partial archive write. Archive IS FLAWED"); |
| 717 |
return(res); |
| 718 |
} |
| 719 |
|
| 720 |
/* |
| 721 |
* ar_rdsync() |
| 722 |
* Try to move past a bad spot on a flawed archive as needed to continue |
| 723 |
* I/O. Clears error flags to allow I/O to continue. |
| 724 |
* Return: |
| 725 |
* 0 when ok to try i/o again, -1 otherwise. |
| 726 |
*/ |
| 727 |
|
| 728 |
int |
| 729 |
ar_rdsync(void) |
| 730 |
{ |
| 731 |
long fsbz; |
| 732 |
off_t cpos; |
| 733 |
off_t mpos; |
| 734 |
#ifndef __INTERIX |
| 735 |
struct mtop mb; |
| 736 |
#endif |
| 737 |
|
| 738 |
/* |
| 739 |
* Fail resync attempts at user request (done) or if this is going to be |
| 740 |
* an update/append to a existing archive. if last i/o hit media end, |
| 741 |
* we need to go to the next volume not try a resync |
| 742 |
*/ |
| 743 |
if ((done > 0) || (lstrval == 0)) |
| 744 |
return(-1); |
| 745 |
|
| 746 |
if ((act == APPND) || (act == ARCHIVE)) { |
| 747 |
paxwarn(1, "Cannot allow updates to an archive with flaws."); |
| 748 |
return(-1); |
| 749 |
} |
| 750 |
if (io_ok) |
| 751 |
did_io = 1; |
| 752 |
|
| 753 |
switch (artyp) { |
| 754 |
#ifndef __INTERIX |
| 755 |
case ISTAPE: |
| 756 |
/* |
| 757 |
* if the last i/o was a successful data transfer, we assume |
| 758 |
* the fault is just a bad record on the tape that we are now |
| 759 |
* past. If we did not get any data since the last resync try |
| 760 |
* to move the tape forward one PHYSICAL record past any |
| 761 |
* damaged tape section. Some tape drives are stubborn and need |
| 762 |
* to be pushed. |
| 763 |
*/ |
| 764 |
if (io_ok) { |
| 765 |
io_ok = 0; |
| 766 |
lstrval = 1; |
| 767 |
break; |
| 768 |
} |
| 769 |
mb.mt_op = MTFSR; |
| 770 |
mb.mt_count = 1; |
| 771 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) |
| 772 |
break; |
| 773 |
lstrval = 1; |
| 774 |
break; |
| 775 |
#endif |
| 776 |
case ISREG: |
| 777 |
case ISCHR: |
| 778 |
case ISBLK: |
| 779 |
/* |
| 780 |
* try to step over the bad part of the device. |
| 781 |
*/ |
| 782 |
io_ok = 0; |
| 783 |
if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) |
| 784 |
fsbz = BLKMULT; |
| 785 |
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) |
| 786 |
break; |
| 787 |
mpos = fsbz - (cpos % (off_t)fsbz); |
| 788 |
if (lseek(arfd, mpos, SEEK_CUR) < 0) |
| 789 |
break; |
| 790 |
lstrval = 1; |
| 791 |
break; |
| 792 |
case ISPIPE: |
| 793 |
default: |
| 794 |
/* |
| 795 |
* cannot recover on these archive device types |
| 796 |
*/ |
| 797 |
io_ok = 0; |
| 798 |
break; |
| 799 |
} |
| 800 |
if (lstrval <= 0) { |
| 801 |
paxwarn(1, "Unable to recover from an archive read failure."); |
| 802 |
return(-1); |
| 803 |
} |
| 804 |
paxwarn(0, "Attempting to recover from an archive read failure."); |
| 805 |
return(0); |
| 806 |
} |
| 807 |
|
| 808 |
/* |
| 809 |
* ar_fow() |
| 810 |
* Move the I/O position within the archive forward the specified number of |
| 811 |
* bytes as supported by the device. If we cannot move the requested |
| 812 |
* number of bytes, return the actual number of bytes moved in skipped. |
| 813 |
* Return: |
| 814 |
* 0 if moved the requested distance, -1 on complete failure, 1 on |
| 815 |
* partial move (the amount moved is in skipped) |
| 816 |
*/ |
| 817 |
|
| 818 |
int |
| 819 |
ar_fow(off_t sksz, off_t *skipped) |
| 820 |
{ |
| 821 |
off_t cpos; |
| 822 |
off_t mpos; |
| 823 |
|
| 824 |
*skipped = 0; |
| 825 |
if (sksz <= 0) |
| 826 |
return(0); |
| 827 |
|
| 828 |
/* |
| 829 |
* we cannot move forward at EOF or error |
| 830 |
*/ |
| 831 |
if (lstrval <= 0) |
| 832 |
return(lstrval); |
| 833 |
|
| 834 |
/* |
| 835 |
* Safer to read forward on devices where it is hard to find the end of |
| 836 |
* the media without reading to it. With tapes we cannot be sure of the |
| 837 |
* number of physical blocks to skip (we do not know physical block |
| 838 |
* size at this point), so we must only read forward on tapes! |
| 839 |
*/ |
| 840 |
if (artyp != ISREG) |
| 841 |
return(0); |
| 842 |
|
| 843 |
/* |
| 844 |
* figure out where we are in the archive |
| 845 |
*/ |
| 846 |
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) { |
| 847 |
/* |
| 848 |
* we can be asked to move farther than there are bytes in this |
| 849 |
* volume, if so, just go to file end and let normal buf_fill() |
| 850 |
* deal with the end of file (it will go to next volume by |
| 851 |
* itself) |
| 852 |
*/ |
| 853 |
if ((mpos = cpos + sksz) > arsb.st_size) { |
| 854 |
*skipped = arsb.st_size - cpos; |
| 855 |
mpos = arsb.st_size; |
| 856 |
} else |
| 857 |
*skipped = sksz; |
| 858 |
if (lseek(arfd, mpos, SEEK_SET) >= 0) |
| 859 |
return(0); |
| 860 |
} |
| 861 |
syswarn(1, errno, "Forward positioning operation on archive failed"); |
| 862 |
lstrval = -1; |
| 863 |
return(-1); |
| 864 |
} |
| 865 |
|
| 866 |
/* |
| 867 |
* ar_rev() |
| 868 |
* move the i/o position within the archive backwards the specified byte |
| 869 |
* count as supported by the device. With tapes drives we RESET rdblksz to |
| 870 |
* the PHYSICAL blocksize. |
| 871 |
* NOTE: We should only be called to move backwards so we can rewrite the |
| 872 |
* last records (the trailer) of an archive (APPEND). |
| 873 |
* Return: |
| 874 |
* 0 if moved the requested distance, -1 on complete failure |
| 875 |
*/ |
| 876 |
|
| 877 |
int |
| 878 |
ar_rev(off_t sksz) |
| 879 |
{ |
| 880 |
off_t cpos; |
| 881 |
#ifndef __INTERIX |
| 882 |
struct mtop mb; |
| 883 |
#endif |
| 884 |
int phyblk; |
| 885 |
|
| 886 |
/* |
| 887 |
* make sure we do not have try to reverse on a flawed archive |
| 888 |
*/ |
| 889 |
if (lstrval < 0) |
| 890 |
return(lstrval); |
| 891 |
|
| 892 |
switch (artyp) { |
| 893 |
case ISPIPE: |
| 894 |
if (sksz <= 0) |
| 895 |
break; |
| 896 |
/* |
| 897 |
* cannot go backwards on these critters |
| 898 |
*/ |
| 899 |
paxwarn(1, "Reverse positioning on pipes is not supported."); |
| 900 |
lstrval = -1; |
| 901 |
return(-1); |
| 902 |
case ISREG: |
| 903 |
case ISBLK: |
| 904 |
case ISCHR: |
| 905 |
default: |
| 906 |
if (sksz <= 0) |
| 907 |
break; |
| 908 |
|
| 909 |
/* |
| 910 |
* For things other than files, backwards movement has a very |
| 911 |
* high probability of failure as we really do not know the |
| 912 |
* true attributes of the device we are talking to (the device |
| 913 |
* may not even have the ability to lseek() in any direction). |
| 914 |
* First we figure out where we are in the archive. |
| 915 |
*/ |
| 916 |
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) { |
| 917 |
syswarn(1, errno, |
| 918 |
"Unable to obtain current archive byte offset"); |
| 919 |
lstrval = -1; |
| 920 |
return(-1); |
| 921 |
} |
| 922 |
|
| 923 |
/* |
| 924 |
* we may try to go backwards past the start when the archive |
| 925 |
* is only a single record. If this happens and we are on a |
| 926 |
* multi-volume archive, we need to go to the end of the |
| 927 |
* previous volume and continue our movement backwards from |
| 928 |
* there. |
| 929 |
*/ |
| 930 |
if ((cpos -= sksz) < (off_t)0L) { |
| 931 |
if (arvol > 1) { |
| 932 |
/* |
| 933 |
* this should never happen |
| 934 |
*/ |
| 935 |
paxwarn(1,"Reverse position on previous volume."); |
| 936 |
lstrval = -1; |
| 937 |
return(-1); |
| 938 |
} |
| 939 |
cpos = (off_t)0L; |
| 940 |
} |
| 941 |
if (lseek(arfd, cpos, SEEK_SET) < 0) { |
| 942 |
syswarn(1, errno, "Unable to seek archive backwards"); |
| 943 |
lstrval = -1; |
| 944 |
return(-1); |
| 945 |
} |
| 946 |
break; |
| 947 |
#ifndef __INTERIX |
| 948 |
case ISTAPE: |
| 949 |
/* |
| 950 |
* Calculate and move the proper number of PHYSICAL tape |
| 951 |
* blocks. If the sksz is not an even multiple of the physical |
| 952 |
* tape size, we cannot do the move (this should never happen). |
| 953 |
* (We also cannot handle trailers spread over two vols.) |
| 954 |
* get_phys() also makes sure we are in front of the filemark. |
| 955 |
*/ |
| 956 |
if ((phyblk = get_phys()) <= 0) { |
| 957 |
lstrval = -1; |
| 958 |
return(-1); |
| 959 |
} |
| 960 |
|
| 961 |
/* |
| 962 |
* make sure future tape reads only go by physical tape block |
| 963 |
* size (set rdblksz to the real size). |
| 964 |
*/ |
| 965 |
rdblksz = phyblk; |
| 966 |
|
| 967 |
/* |
| 968 |
* if no movement is required, just return (we must be after |
| 969 |
* get_phys() so the physical blocksize is properly set) |
| 970 |
*/ |
| 971 |
if (sksz <= 0) |
| 972 |
break; |
| 973 |
|
| 974 |
/* |
| 975 |
* ok we have to move. Make sure the tape drive can do it. |
| 976 |
*/ |
| 977 |
if (sksz % phyblk) { |
| 978 |
paxwarn(1, |
| 979 |
"Tape drive unable to backspace requested amount"); |
| 980 |
lstrval = -1; |
| 981 |
return(-1); |
| 982 |
} |
| 983 |
|
| 984 |
/* |
| 985 |
* move backwards the requested number of bytes |
| 986 |
*/ |
| 987 |
mb.mt_op = MTBSR; |
| 988 |
mb.mt_count = sksz/phyblk; |
| 989 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) { |
| 990 |
syswarn(1,errno, "Unable to backspace tape %d blocks.", |
| 991 |
mb.mt_count); |
| 992 |
lstrval = -1; |
| 993 |
return(-1); |
| 994 |
} |
| 995 |
break; |
| 996 |
#endif |
| 997 |
} |
| 998 |
lstrval = 1; |
| 999 |
return(0); |
| 1000 |
} |
| 1001 |
|
| 1002 |
#ifndef __INTERIX |
| 1003 |
/* |
| 1004 |
* get_phys() |
| 1005 |
* Determine the physical block size on a tape drive. We need the physical |
| 1006 |
* block size so we know how many bytes we skip over when we move with |
| 1007 |
* mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when |
| 1008 |
* return. |
| 1009 |
* This is one really SLOW routine... |
| 1010 |
* Return: |
| 1011 |
* physical block size if ok (ok > 0), -1 otherwise |
| 1012 |
*/ |
| 1013 |
|
| 1014 |
static int |
| 1015 |
get_phys(void) |
| 1016 |
{ |
| 1017 |
int padsz = 0; |
| 1018 |
int res; |
| 1019 |
int phyblk; |
| 1020 |
struct mtop mb; |
| 1021 |
char scbuf[MAXBLK]; |
| 1022 |
|
| 1023 |
/* |
| 1024 |
* move to the file mark, and then back up one record and read it. |
| 1025 |
* this should tell us the physical record size the tape is using. |
| 1026 |
*/ |
| 1027 |
if (lstrval == 1) { |
| 1028 |
/* |
| 1029 |
* we know we are at file mark when we get back a 0 from |
| 1030 |
* read() |
| 1031 |
*/ |
| 1032 |
while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) |
| 1033 |
padsz += res; |
| 1034 |
if (res < 0) { |
| 1035 |
syswarn(1, errno, "Unable to locate tape filemark."); |
| 1036 |
return(-1); |
| 1037 |
} |
| 1038 |
} |
| 1039 |
|
| 1040 |
/* |
| 1041 |
* move backwards over the file mark so we are at the end of the |
| 1042 |
* last record. |
| 1043 |
*/ |
| 1044 |
mb.mt_op = MTBSF; |
| 1045 |
mb.mt_count = 1; |
| 1046 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) { |
| 1047 |
syswarn(1, errno, "Unable to backspace over tape filemark."); |
| 1048 |
return(-1); |
| 1049 |
} |
| 1050 |
|
| 1051 |
/* |
| 1052 |
* move backwards so we are in front of the last record and read it to |
| 1053 |
* get physical tape blocksize. |
| 1054 |
*/ |
| 1055 |
mb.mt_op = MTBSR; |
| 1056 |
mb.mt_count = 1; |
| 1057 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) { |
| 1058 |
syswarn(1, errno, "Unable to backspace over last tape block."); |
| 1059 |
return(-1); |
| 1060 |
} |
| 1061 |
if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) { |
| 1062 |
syswarn(1, errno, "Cannot determine archive tape blocksize."); |
| 1063 |
return(-1); |
| 1064 |
} |
| 1065 |
|
| 1066 |
/* |
| 1067 |
* read forward to the file mark, then back up in front of the filemark |
| 1068 |
* (this is a bit paranoid, but should be safe to do). |
| 1069 |
*/ |
| 1070 |
while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) |
| 1071 |
; |
| 1072 |
if (res < 0) { |
| 1073 |
syswarn(1, errno, "Unable to locate tape filemark."); |
| 1074 |
return(-1); |
| 1075 |
} |
| 1076 |
mb.mt_op = MTBSF; |
| 1077 |
mb.mt_count = 1; |
| 1078 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) { |
| 1079 |
syswarn(1, errno, "Unable to backspace over tape filemark."); |
| 1080 |
return(-1); |
| 1081 |
} |
| 1082 |
|
| 1083 |
/* |
| 1084 |
* set lstrval so we know that the filemark has not been seen |
| 1085 |
*/ |
| 1086 |
lstrval = 1; |
| 1087 |
|
| 1088 |
/* |
| 1089 |
* return if there was no padding |
| 1090 |
*/ |
| 1091 |
if (padsz == 0) |
| 1092 |
return(phyblk); |
| 1093 |
|
| 1094 |
/* |
| 1095 |
* make sure we can move backwards over the padding. (this should |
| 1096 |
* never fail). |
| 1097 |
*/ |
| 1098 |
if (padsz % phyblk) { |
| 1099 |
paxwarn(1, "Tape drive unable to backspace requested amount"); |
| 1100 |
return(-1); |
| 1101 |
} |
| 1102 |
|
| 1103 |
/* |
| 1104 |
* move backwards over the padding so the head is where it was when |
| 1105 |
* we were first called (if required). |
| 1106 |
*/ |
| 1107 |
mb.mt_op = MTBSR; |
| 1108 |
mb.mt_count = padsz/phyblk; |
| 1109 |
if (ioctl(arfd, MTIOCTOP, &mb) < 0) { |
| 1110 |
syswarn(1,errno,"Unable to backspace tape over %d pad blocks", |
| 1111 |
mb.mt_count); |
| 1112 |
return(-1); |
| 1113 |
} |
| 1114 |
return(phyblk); |
| 1115 |
} |
| 1116 |
#endif |
| 1117 |
|
| 1118 |
/* |
| 1119 |
* ar_next() |
| 1120 |
* prompts the user for the next volume in this archive. For some devices |
| 1121 |
* we may allow the media to be changed. Otherwise a new archive is |
| 1122 |
* prompted for. By pax spec, if there is no controlling tty or an eof is |
| 1123 |
* read on tty input, we must quit pax. |
| 1124 |
* Return: |
| 1125 |
* 0 when ready to continue, -1 when all done |
| 1126 |
*/ |
| 1127 |
|
| 1128 |
int |
| 1129 |
ar_next(void) |
| 1130 |
{ |
| 1131 |
char buf[PAXPATHLEN+2]; |
| 1132 |
static int freeit = 0; |
| 1133 |
sigset_t o_mask; |
| 1134 |
|
| 1135 |
/* |
| 1136 |
* WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so |
| 1137 |
* things like writing EOF etc will be done) (Watch out ar_close() can |
| 1138 |
* also be called via a signal handler, so we must prevent a race. |
| 1139 |
*/ |
| 1140 |
if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0) |
| 1141 |
syswarn(0, errno, "Unable to set signal mask"); |
| 1142 |
ar_close(); |
| 1143 |
if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0) |
| 1144 |
syswarn(0, errno, "Unable to restore signal mask"); |
| 1145 |
|
| 1146 |
if (done || !wr_trail || force_one_volume || strcmp(NM_TAR, argv0) == 0) |
| 1147 |
return(-1); |
| 1148 |
|
| 1149 |
tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0); |
| 1150 |
|
| 1151 |
/* |
| 1152 |
* if i/o is on stdin or stdout, we cannot reopen it (we do not know |
| 1153 |
* the name), the user will be forced to type it in. |
| 1154 |
*/ |
| 1155 |
if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG) |
| 1156 |
&& (artyp != ISPIPE)) { |
| 1157 |
if (artyp == ISTAPE) { |
| 1158 |
tty_prnt("%s ready for archive tape volume: %d\n", |
| 1159 |
arcname, arvol); |
| 1160 |
tty_prnt("Load the NEXT TAPE on the tape drive"); |
| 1161 |
} else { |
| 1162 |
tty_prnt("%s ready for archive volume: %d\n", |
| 1163 |
arcname, arvol); |
| 1164 |
tty_prnt("Load the NEXT STORAGE MEDIA (if required)"); |
| 1165 |
} |
| 1166 |
|
| 1167 |
if ((act == ARCHIVE) || (act == APPND)) |
| 1168 |
tty_prnt(" and make sure it is WRITE ENABLED.\n"); |
| 1169 |
else |
| 1170 |
tty_prnt("\n"); |
| 1171 |
|
| 1172 |
for (;;) { |
| 1173 |
tty_prnt("Type \"y\" to continue, \".\" to quit %s,", |
| 1174 |
argv0); |
| 1175 |
tty_prnt(" or \"s\" to switch to new device.\nIf you"); |
| 1176 |
tty_prnt(" cannot change storage media, type \"s\"\n"); |
| 1177 |
tty_prnt("Is the device ready and online? > "); |
| 1178 |
|
| 1179 |
if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){ |
| 1180 |
done = 1; |
| 1181 |
lstrval = -1; |
| 1182 |
tty_prnt("Quitting %s!\n", argv0); |
| 1183 |
vfpart = 0; |
| 1184 |
return(-1); |
| 1185 |
} |
| 1186 |
|
| 1187 |
if ((buf[0] == '\0') || (buf[1] != '\0')) { |
| 1188 |
tty_prnt("%s unknown command, try again\n",buf); |
| 1189 |
continue; |
| 1190 |
} |
| 1191 |
|
| 1192 |
switch (buf[0]) { |
| 1193 |
case 'y': |
| 1194 |
case 'Y': |
| 1195 |
/* |
| 1196 |
* we are to continue with the same device |
| 1197 |
*/ |
| 1198 |
if (ar_open(arcname) >= 0) |
| 1199 |
return(0); |
| 1200 |
tty_prnt("Cannot re-open %s, try again\n", |
| 1201 |
arcname); |
| 1202 |
continue; |
| 1203 |
case 's': |
| 1204 |
case 'S': |
| 1205 |
/* |
| 1206 |
* user wants to open a different device |
| 1207 |
*/ |
| 1208 |
tty_prnt("Switching to a different archive\n"); |
| 1209 |
break; |
| 1210 |
default: |
| 1211 |
tty_prnt("%s unknown command, try again\n",buf); |
| 1212 |
continue; |
| 1213 |
} |
| 1214 |
break; |
| 1215 |
} |
| 1216 |
} else |
| 1217 |
tty_prnt("Ready for archive volume: %d\n", arvol); |
| 1218 |
|
| 1219 |
/* |
| 1220 |
* have to go to a different archive |
| 1221 |
*/ |
| 1222 |
for (;;) { |
| 1223 |
tty_prnt("Input archive name or \".\" to quit %s.\n", argv0); |
| 1224 |
tty_prnt("Archive name > "); |
| 1225 |
|
| 1226 |
if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) { |
| 1227 |
done = 1; |
| 1228 |
lstrval = -1; |
| 1229 |
tty_prnt("Quitting %s!\n", argv0); |
| 1230 |
vfpart = 0; |
| 1231 |
return(-1); |
| 1232 |
} |
| 1233 |
if (buf[0] == '\0') { |
| 1234 |
tty_prnt("Empty file name, try again\n"); |
| 1235 |
continue; |
| 1236 |
} |
| 1237 |
if (!strcmp(buf, "..")) { |
| 1238 |
tty_prnt("Illegal file name: .. try again\n"); |
| 1239 |
continue; |
| 1240 |
} |
| 1241 |
if (strlen(buf) > PAXPATHLEN) { |
| 1242 |
tty_prnt("File name too long, try again\n"); |
| 1243 |
continue; |
| 1244 |
} |
| 1245 |
|
| 1246 |
/* |
| 1247 |
* try to open new archive |
| 1248 |
*/ |
| 1249 |
if (ar_open(buf) >= 0) { |
| 1250 |
if (freeit) { |
| 1251 |
free(arcname_); |
| 1252 |
freeit = 0; |
| 1253 |
} |
| 1254 |
if ((arcname = arcname_ = strdup(buf)) == NULL) { |
| 1255 |
done = 1; |
| 1256 |
lstrval = -1; |
| 1257 |
paxwarn(0, "Cannot save archive name."); |
| 1258 |
return(-1); |
| 1259 |
} |
| 1260 |
freeit = 1; |
| 1261 |
break; |
| 1262 |
} |
| 1263 |
tty_prnt("Cannot open %s, try again\n", buf); |
| 1264 |
continue; |
| 1265 |
} |
| 1266 |
return(0); |
| 1267 |
} |
| 1268 |
|
| 1269 |
/* |
| 1270 |
* ar_start_gzip() |
| 1271 |
* starts the gzip compression/decompression process as a child, using magic |
| 1272 |
* to keep the fd the same in the calling function (parent). |
| 1273 |
*/ |
| 1274 |
void |
| 1275 |
ar_start_gzip(int fd, int wr) |
| 1276 |
{ |
| 1277 |
int fds[2]; |
| 1278 |
const char *gzip_flags; |
| 1279 |
|
| 1280 |
if (pipe(fds) < 0) |
| 1281 |
err(1, "could not pipe"); |
| 1282 |
zpid = fork(); |
| 1283 |
if (zpid < 0) |
| 1284 |
err(1, "could not fork"); |
| 1285 |
|
| 1286 |
/* parent */ |
| 1287 |
if (zpid) { |
| 1288 |
if (wr) |
| 1289 |
dup2(fds[1], fd); |
| 1290 |
else |
| 1291 |
dup2(fds[0], fd); |
| 1292 |
close(fds[0]); |
| 1293 |
close(fds[1]); |
| 1294 |
} else { |
| 1295 |
if (wr) { |
| 1296 |
dup2(fds[0], STDIN_FILENO); |
| 1297 |
dup2(fd, STDOUT_FILENO); |
| 1298 |
gzip_flags = "-c"; |
| 1299 |
} else { |
| 1300 |
dup2(fds[1], STDOUT_FILENO); |
| 1301 |
dup2(fd, STDIN_FILENO); |
| 1302 |
gzip_flags = "-dc"; |
| 1303 |
} |
| 1304 |
close(fds[0]); |
| 1305 |
close(fds[1]); |
| 1306 |
if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0) |
| 1307 |
err(1, "could not exec"); |
| 1308 |
/* NOTREACHED */ |
| 1309 |
} |
| 1310 |
} |