11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1992 Keith Muller. 31556Srgrimes * Copyright (c) 1992, 1993 41556Srgrimes * The Regents of the University of California. All rights reserved. 51556Srgrimes * 61556Srgrimes * This code is derived from software contributed to Berkeley by 71556Srgrimes * Keith Muller of the University of California, San Diego. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 321556Srgrimes */ 331556Srgrimes 341556Srgrimes#ifndef lint 3536049Scharnier#if 0 3636049Scharnierstatic char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; 3736049Scharnier#endif 381556Srgrimes#endif /* not lint */ 3999110Sobrien#include <sys/cdefs.h> 4099110Sobrien__FBSDID("$FreeBSD$"); 411556Srgrimes 421556Srgrimes#include <sys/types.h> 431556Srgrimes#include <sys/ioctl.h> 441556Srgrimes#include <sys/mtio.h> 4576286Skris#include <sys/stat.h> 4676286Skris#include <sys/wait.h> 4776286Skris#include <err.h> 4876286Skris#include <errno.h> 4976286Skris#include <fcntl.h> 501556Srgrimes#include <signal.h> 51104548Stjr#include <stdint.h> 5276286Skris#include <stdio.h> 531556Srgrimes#include <string.h> 5476286Skris#include <stdlib.h> 551556Srgrimes#include <unistd.h> 561556Srgrimes#include "pax.h" 5776351Skris#include "options.h" 581556Srgrimes#include "extern.h" 591556Srgrimes 601556Srgrimes/* 611556Srgrimes * Routines which deal directly with the archive I/O device/file. 621556Srgrimes */ 631556Srgrimes 641556Srgrimes#define DMOD 0666 /* default mode of created archives */ 651556Srgrimes#define EXT_MODE O_RDONLY /* open mode for list/extract */ 661556Srgrimes#define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */ 671556Srgrimes#define APP_MODE O_RDWR /* mode for append */ 68114583Smarkm 69114583Smarkmstatic char none[] = "<NONE>"; /* pseudo name for no file */ 70114583Smarkmstatic char stdo[] = "<STDOUT>"; /* pseudo name for stdout */ 71114583Smarkmstatic char stdn[] = "<STDIN>"; /* pseudo name for stdin */ 721556Srgrimesstatic int arfd = -1; /* archive file descriptor */ 731556Srgrimesstatic int artyp = ISREG; /* archive type: file/FIFO/tape */ 741556Srgrimesstatic int arvol = 1; /* archive volume number */ 751556Srgrimesstatic int lstrval = -1; /* return value from last i/o */ 761556Srgrimesstatic int io_ok; /* i/o worked on volume after resync */ 771556Srgrimesstatic int did_io; /* did i/o ever occur on volume? */ 781556Srgrimesstatic int done; /* set via tty termination */ 791556Srgrimesstatic struct stat arsb; /* stat of archive device at open */ 801556Srgrimesstatic int invld_rec; /* tape has out of spec record size */ 811556Srgrimesstatic int wr_trail = 1; /* trailer was rewritten in append */ 821556Srgrimesstatic int can_unlnk = 0; /* do we unlink null archives? */ 83114583Smarkmconst char *arcname; /* printable name of archive */ 8476286Skrisconst char *gzip_program; /* name of gzip program */ 8576286Skrisstatic pid_t zpid = -1; /* pid of child process */ 861556Srgrimes 8790110Simpstatic int get_phys(void); 8890110Simpstatic void ar_start_gzip(int, const char *, int); 891556Srgrimes 901556Srgrimes/* 911556Srgrimes * ar_open() 921556Srgrimes * Opens the next archive volume. Determines the type of the device and 931556Srgrimes * sets up block sizes as required by the archive device and the format. 941556Srgrimes * Note: we may be called with name == NULL on the first open only. 951556Srgrimes * Return: 961556Srgrimes * -1 on failure, 0 otherwise 971556Srgrimes */ 981556Srgrimes 991556Srgrimesint 100114583Smarkmar_open(const char *name) 1011556Srgrimes{ 10276019Skris struct mtget mb; 1031556Srgrimes 1041556Srgrimes if (arfd != -1) 1051556Srgrimes (void)close(arfd); 1061556Srgrimes arfd = -1; 1071556Srgrimes can_unlnk = did_io = io_ok = invld_rec = 0; 1081556Srgrimes artyp = ISREG; 1091556Srgrimes flcnt = 0; 1101556Srgrimes 1111556Srgrimes /* 1121556Srgrimes * open based on overall operation mode 1131556Srgrimes */ 1141556Srgrimes switch (act) { 1151556Srgrimes case LIST: 1161556Srgrimes case EXTRACT: 1171556Srgrimes if (name == NULL) { 1181556Srgrimes arfd = STDIN_FILENO; 119114583Smarkm arcname = stdn; 1201556Srgrimes } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) 12176017Skris syswarn(0, errno, "Failed open to read on %s", name); 12276286Skris if (arfd != -1 && gzip_program != NULL) 12376286Skris ar_start_gzip(arfd, gzip_program, 0); 1241556Srgrimes break; 1251556Srgrimes case ARCHIVE: 1261556Srgrimes if (name == NULL) { 1271556Srgrimes arfd = STDOUT_FILENO; 128114583Smarkm arcname = stdo; 1291556Srgrimes } else if ((arfd = open(name, AR_MODE, DMOD)) < 0) 13076017Skris syswarn(0, errno, "Failed open to write on %s", name); 1311556Srgrimes else 1321556Srgrimes can_unlnk = 1; 13376286Skris if (arfd != -1 && gzip_program != NULL) 13476286Skris ar_start_gzip(arfd, gzip_program, 1); 1351556Srgrimes break; 1361556Srgrimes case APPND: 1371556Srgrimes if (name == NULL) { 1381556Srgrimes arfd = STDOUT_FILENO; 139114583Smarkm arcname = stdo; 1401556Srgrimes } else if ((arfd = open(name, APP_MODE, DMOD)) < 0) 14176017Skris syswarn(0, errno, "Failed open to read/write on %s", 1421556Srgrimes name); 1431556Srgrimes break; 1441556Srgrimes case COPY: 1451556Srgrimes /* 1461556Srgrimes * arfd not used in COPY mode 1471556Srgrimes */ 148114583Smarkm arcname = none; 1491556Srgrimes lstrval = 1; 1501556Srgrimes return(0); 1511556Srgrimes } 1521556Srgrimes if (arfd < 0) 1531556Srgrimes return(-1); 1541556Srgrimes 15576351Skris if (chdname != NULL) 156131085Sobrien if (chdir(chdname) != 0) { 15776351Skris syswarn(1, errno, "Failed chdir to %s", chdname); 158131085Sobrien return(-1); 159131085Sobrien } 1601556Srgrimes /* 1611556Srgrimes * set up is based on device type 1621556Srgrimes */ 1631556Srgrimes if (fstat(arfd, &arsb) < 0) { 16476017Skris syswarn(0, errno, "Failed stat on %s", arcname); 1651556Srgrimes (void)close(arfd); 1661556Srgrimes arfd = -1; 1671556Srgrimes can_unlnk = 0; 1681556Srgrimes return(-1); 1691556Srgrimes } 1701556Srgrimes if (S_ISDIR(arsb.st_mode)) { 17176017Skris paxwarn(0, "Cannot write an archive on top of a directory %s", 1721556Srgrimes arcname); 1731556Srgrimes (void)close(arfd); 1741556Srgrimes arfd = -1; 1751556Srgrimes can_unlnk = 0; 1761556Srgrimes return(-1); 1771556Srgrimes } 1781556Srgrimes 1791556Srgrimes if (S_ISCHR(arsb.st_mode)) 1801556Srgrimes artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; 1811556Srgrimes else if (S_ISBLK(arsb.st_mode)) 1821556Srgrimes artyp = ISBLK; 1831556Srgrimes else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) 1841556Srgrimes artyp = ISPIPE; 1851556Srgrimes else 1861556Srgrimes artyp = ISREG; 1871556Srgrimes 1881556Srgrimes /* 1891556Srgrimes * make sure we beyond any doubt that we only can unlink regular files 1901556Srgrimes * we created 1911556Srgrimes */ 1921556Srgrimes if (artyp != ISREG) 1931556Srgrimes can_unlnk = 0; 1941556Srgrimes /* 1951556Srgrimes * if we are writing, we are done 1961556Srgrimes */ 1971556Srgrimes if (act == ARCHIVE) { 1981556Srgrimes blksz = rdblksz = wrblksz; 1991556Srgrimes lstrval = 1; 2001556Srgrimes return(0); 2011556Srgrimes } 2021556Srgrimes 2031556Srgrimes /* 2041556Srgrimes * set default blksz on read. APPNDs writes rdblksz on the last volume 2051556Srgrimes * On all new archive volumes, we shift to wrblksz (if the user 206222177Suqs * specified one, otherwise we will continue to use rdblksz). We 2071556Srgrimes * must to set blocksize based on what kind of device the archive is 2081556Srgrimes * stored. 2091556Srgrimes */ 2101556Srgrimes switch(artyp) { 2111556Srgrimes case ISTAPE: 2121556Srgrimes /* 2131556Srgrimes * Tape drives come in at least two flavors. Those that support 2141556Srgrimes * variable sized records and those that have fixed sized 2151556Srgrimes * records. They must be treated differently. For tape drives 2161556Srgrimes * that support variable sized records, we must make large 2171556Srgrimes * reads to make sure we get the entire record, otherwise we 2181556Srgrimes * will just get the first part of the record (up to size we 2191556Srgrimes * asked). Tapes with fixed sized records may or may not return 2201556Srgrimes * multiple records in a single read. We really do not care 2211556Srgrimes * what the physical record size is UNLESS we are going to 2221556Srgrimes * append. (We will need the physical block size to rewrite 2231556Srgrimes * the trailer). Only when we are appending do we go to the 2241556Srgrimes * effort to figure out the true PHYSICAL record size. 2251556Srgrimes */ 2261556Srgrimes blksz = rdblksz = MAXBLK; 2271556Srgrimes break; 2281556Srgrimes case ISPIPE: 2291556Srgrimes case ISBLK: 2301556Srgrimes case ISCHR: 2311556Srgrimes /* 2321556Srgrimes * Blocksize is not a major issue with these devices (but must 2331556Srgrimes * be kept a multiple of 512). If the user specified a write 2341556Srgrimes * block size, we use that to read. Under append, we must 2351556Srgrimes * always keep blksz == rdblksz. Otherwise we go ahead and use 2361556Srgrimes * the device optimal blocksize as (and if) returned by stat 2371556Srgrimes * and if it is within pax specs. 2381556Srgrimes */ 2391556Srgrimes if ((act == APPND) && wrblksz) { 2401556Srgrimes blksz = rdblksz = wrblksz; 2411556Srgrimes break; 2421556Srgrimes } 2431556Srgrimes 2441556Srgrimes if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && 2451556Srgrimes ((arsb.st_blksize % BLKMULT) == 0)) 2461556Srgrimes rdblksz = arsb.st_blksize; 2471556Srgrimes else 2481556Srgrimes rdblksz = DEVBLK; 2491556Srgrimes /* 2501556Srgrimes * For performance go for large reads when we can without harm 2511556Srgrimes */ 2521556Srgrimes if ((act == APPND) || (artyp == ISCHR)) 2531556Srgrimes blksz = rdblksz; 2541556Srgrimes else 2551556Srgrimes blksz = MAXBLK; 2561556Srgrimes break; 2571556Srgrimes case ISREG: 2581556Srgrimes /* 2591556Srgrimes * if the user specified wrblksz works, use it. Under appends 2601556Srgrimes * we must always keep blksz == rdblksz 2611556Srgrimes */ 2621556Srgrimes if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ 2631556Srgrimes blksz = rdblksz = wrblksz; 2641556Srgrimes break; 2651556Srgrimes } 2661556Srgrimes /* 2671556Srgrimes * See if we can find the blocking factor from the file size 2681556Srgrimes */ 2691556Srgrimes for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) 2701556Srgrimes if ((arsb.st_size % rdblksz) == 0) 2711556Srgrimes break; 2721556Srgrimes /* 27346684Skris * When we cannot find a match, we may have a flawed archive. 2741556Srgrimes */ 2751556Srgrimes if (rdblksz <= 0) 2761556Srgrimes rdblksz = FILEBLK; 2771556Srgrimes /* 2781556Srgrimes * for performance go for large reads when we can 2791556Srgrimes */ 2801556Srgrimes if (act == APPND) 2811556Srgrimes blksz = rdblksz; 2821556Srgrimes else 2831556Srgrimes blksz = MAXBLK; 2841556Srgrimes break; 2851556Srgrimes default: 2861556Srgrimes /* 2878855Srgrimes * should never happen, worse case, slow... 2881556Srgrimes */ 2891556Srgrimes blksz = rdblksz = BLKMULT; 2901556Srgrimes break; 2911556Srgrimes } 2921556Srgrimes lstrval = 1; 2931556Srgrimes return(0); 2941556Srgrimes} 2951556Srgrimes 2961556Srgrimes/* 2971556Srgrimes * ar_close() 2981556Srgrimes * closes archive device, increments volume number, and prints i/o summary 2991556Srgrimes */ 3001556Srgrimesvoid 3011556Srgrimesar_close(void) 3021556Srgrimes{ 303143447Sobrien int status; 3041556Srgrimes 3051556Srgrimes if (arfd < 0) { 3061556Srgrimes did_io = io_ok = flcnt = 0; 3071556Srgrimes return; 3081556Srgrimes } 3091556Srgrimes 3101556Srgrimes /* 3111556Srgrimes * Close archive file. This may take a LONG while on tapes (we may be 3121556Srgrimes * forced to wait for the rewind to complete) so tell the user what is 3131556Srgrimes * going on (this avoids the user hitting control-c thinking pax is 3141556Srgrimes * broken). 3151556Srgrimes */ 3161556Srgrimes if (vflag && (artyp == ISTAPE)) { 3171556Srgrimes if (vfpart) 31876351Skris (void)putc('\n', listf); 31976351Skris (void)fprintf(listf, 3201556Srgrimes "%s: Waiting for tape drive close to complete...", 3211556Srgrimes argv0); 32276351Skris (void)fflush(listf); 3231556Srgrimes } 3241556Srgrimes 3251556Srgrimes /* 3261556Srgrimes * if nothing was written to the archive (and we created it), we remove 3271556Srgrimes * it 3281556Srgrimes */ 3291556Srgrimes if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && 3301556Srgrimes (arsb.st_size == 0)) { 3311556Srgrimes (void)unlink(arcname); 3321556Srgrimes can_unlnk = 0; 3331556Srgrimes } 3341556Srgrimes 33576286Skris /* 33676286Skris * for a quick extract/list, pax frequently exits before the child 33776286Skris * process is done 33876286Skris */ 339143447Sobrien if ((act == LIST || act == EXTRACT) && nflag && zpid > 0) 34076286Skris kill(zpid, SIGINT); 34176286Skris 3421556Srgrimes (void)close(arfd); 3431556Srgrimes 344143447Sobrien /* Do not exit before child to ensure data integrity */ 345143447Sobrien if (zpid > 0) 346143447Sobrien waitpid(zpid, &status, 0); 347143447Sobrien 3481556Srgrimes if (vflag && (artyp == ISTAPE)) { 34976351Skris (void)fputs("done.\n", listf); 3501556Srgrimes vfpart = 0; 35176351Skris (void)fflush(listf); 3521556Srgrimes } 3531556Srgrimes arfd = -1; 3541556Srgrimes 3551556Srgrimes if (!io_ok && !did_io) { 3561556Srgrimes flcnt = 0; 3571556Srgrimes return; 3581556Srgrimes } 3591556Srgrimes did_io = io_ok = 0; 3601556Srgrimes 3611556Srgrimes /* 3621556Srgrimes * The volume number is only increased when the last device has data 3631556Srgrimes * and we have already determined the archive format. 3641556Srgrimes */ 3651556Srgrimes if (frmt != NULL) 3661556Srgrimes ++arvol; 3671556Srgrimes 3681556Srgrimes if (!vflag) { 3691556Srgrimes flcnt = 0; 3701556Srgrimes return; 3711556Srgrimes } 3721556Srgrimes 3731556Srgrimes /* 3741556Srgrimes * Print out a summary of I/O for this archive volume. 3751556Srgrimes */ 3761556Srgrimes if (vfpart) { 37776351Skris (void)putc('\n', listf); 3781556Srgrimes vfpart = 0; 3791556Srgrimes } 3801556Srgrimes 3811556Srgrimes /* 3821556Srgrimes * If we have not determined the format yet, we just say how many bytes 383222177Suqs * we have skipped over looking for a header to id. There is no way we 3841556Srgrimes * could have written anything yet. 3851556Srgrimes */ 3861556Srgrimes if (frmt == NULL) { 3871556Srgrimes# ifdef NET2_STAT 38876351Skris (void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n", 389104548Stjr argv0, rdcnt); 3901556Srgrimes# else 391104548Stjr (void)fprintf(listf, "%s: unknown format, %ju bytes skipped.\n", 392104548Stjr argv0, (uintmax_t)rdcnt); 3931556Srgrimes# endif 39476351Skris (void)fflush(listf); 3951556Srgrimes flcnt = 0; 3961556Srgrimes return; 3971556Srgrimes } 3981556Srgrimes 39976351Skris if (strcmp(NM_CPIO, argv0) == 0) 400104548Stjr (void)fprintf(listf, "%llu blocks\n", 401104548Stjr (unsigned long long)((rdcnt ? rdcnt : wrcnt) / 5120)); 40276351Skris else if (strcmp(NM_TAR, argv0) != 0) 40376351Skris (void)fprintf(listf, 4041556Srgrimes# ifdef NET2_STAT 40576019Skris "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n", 406104548Stjr argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt); 4071556Srgrimes# else 408104548Stjr "%s: %s vol %d, %ju files, %ju bytes read, %ju bytes written.\n", 409104548Stjr argv0, frmt->name, arvol-1, (uintmax_t)flcnt, 410104548Stjr (uintmax_t)rdcnt, (uintmax_t)wrcnt); 4111556Srgrimes# endif 41276351Skris (void)fflush(listf); 4131556Srgrimes flcnt = 0; 4141556Srgrimes} 4151556Srgrimes 4161556Srgrimes/* 4171556Srgrimes * ar_drain() 4181556Srgrimes * drain any archive format independent padding from an archive read 4191556Srgrimes * from a socket or a pipe. This is to prevent the process on the 4201556Srgrimes * other side of the pipe from getting a SIGPIPE (pax will stop 4211556Srgrimes * reading an archive once a format dependent trailer is detected). 4221556Srgrimes */ 4231556Srgrimesvoid 4241556Srgrimesar_drain(void) 4251556Srgrimes{ 42690113Simp int res; 4271556Srgrimes char drbuf[MAXBLK]; 4281556Srgrimes 4291556Srgrimes /* 4301556Srgrimes * we only drain from a pipe/socket. Other devices can be closed 4311556Srgrimes * without reading up to end of file. We sure hope that pipe is closed 4321556Srgrimes * on the other side so we will get an EOF. 4331556Srgrimes */ 4341556Srgrimes if ((artyp != ISPIPE) || (lstrval <= 0)) 4351556Srgrimes return; 4361556Srgrimes 4371556Srgrimes /* 4381556Srgrimes * keep reading until pipe is drained 4391556Srgrimes */ 4401556Srgrimes while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) 4411556Srgrimes ; 4421556Srgrimes lstrval = res; 4431556Srgrimes} 4441556Srgrimes 4451556Srgrimes/* 4461556Srgrimes * ar_set_wr() 4471556Srgrimes * Set up device right before switching from read to write in an append. 4481556Srgrimes * device dependent code (if required) to do this should be added here. 4491556Srgrimes * For all archive devices we are already positioned at the place we want 4501556Srgrimes * to start writing when this routine is called. 4511556Srgrimes * Return: 4521556Srgrimes * 0 if all ready to write, -1 otherwise 4531556Srgrimes */ 4541556Srgrimes 4551556Srgrimesint 4561556Srgrimesar_set_wr(void) 4571556Srgrimes{ 4581556Srgrimes off_t cpos; 4591556Srgrimes 4601556Srgrimes /* 4611556Srgrimes * we must make sure the trailer is rewritten on append, ar_next() 4621556Srgrimes * will stop us if the archive containing the trailer was not written 4631556Srgrimes */ 4641556Srgrimes wr_trail = 0; 4658855Srgrimes 4668855Srgrimes /* 4671556Srgrimes * Add any device dependent code as required here 4681556Srgrimes */ 4691556Srgrimes if (artyp != ISREG) 4701556Srgrimes return(0); 4711556Srgrimes /* 4721556Srgrimes * Ok we have an archive in a regular file. If we were rewriting a 4731556Srgrimes * file, we must get rid of all the stuff after the current offset 4741556Srgrimes * (it was not written by pax). 4751556Srgrimes */ 4761556Srgrimes if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) || 4771556Srgrimes (ftruncate(arfd, cpos) < 0)) { 47876017Skris syswarn(1, errno, "Unable to truncate archive file"); 4791556Srgrimes return(-1); 4801556Srgrimes } 4811556Srgrimes return(0); 4821556Srgrimes} 4831556Srgrimes 4841556Srgrimes/* 4851556Srgrimes * ar_app_ok() 4861556Srgrimes * check if the last volume in the archive allows appends. We cannot check 4878855Srgrimes * this until we are ready to write since there is no spec that says all 4881556Srgrimes * volumes in a single archive have to be of the same type... 4891556Srgrimes * Return: 4901556Srgrimes * 0 if we can append, -1 otherwise. 4911556Srgrimes */ 4921556Srgrimes 4931556Srgrimesint 4941556Srgrimesar_app_ok(void) 4951556Srgrimes{ 4961556Srgrimes if (artyp == ISPIPE) { 49776017Skris paxwarn(1, "Cannot append to an archive obtained from a pipe."); 4981556Srgrimes return(-1); 4991556Srgrimes } 5001556Srgrimes 5011556Srgrimes if (!invld_rec) 5021556Srgrimes return(0); 50376017Skris paxwarn(1,"Cannot append, device record size %d does not support %s spec", 5041556Srgrimes rdblksz, argv0); 5051556Srgrimes return(-1); 5061556Srgrimes} 5071556Srgrimes 5081556Srgrimes/* 5091556Srgrimes * ar_read() 5101556Srgrimes * read up to a specified number of bytes from the archive into the 5111556Srgrimes * supplied buffer. When dealing with tapes we may not always be able to 5121556Srgrimes * read what we want. 5131556Srgrimes * Return: 5141556Srgrimes * Number of bytes in buffer. 0 for end of file, -1 for a read error. 5151556Srgrimes */ 5161556Srgrimes 5171556Srgrimesint 51890113Simpar_read(char *buf, int cnt) 5191556Srgrimes{ 52090113Simp int res = 0; 5211556Srgrimes 5221556Srgrimes /* 5231556Srgrimes * if last i/o was in error, no more reads until reset or new volume 5241556Srgrimes */ 5251556Srgrimes if (lstrval <= 0) 5261556Srgrimes return(lstrval); 5271556Srgrimes 5281556Srgrimes /* 5291556Srgrimes * how we read must be based on device type 5301556Srgrimes */ 5311556Srgrimes switch (artyp) { 5321556Srgrimes case ISTAPE: 5331556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5341556Srgrimes /* 5351556Srgrimes * CAUTION: tape systems may not always return the same 5361556Srgrimes * sized records so we leave blksz == MAXBLK. The 5371556Srgrimes * physical record size that a tape drive supports is 5381556Srgrimes * very hard to determine in a uniform and portable 5391556Srgrimes * manner. 5401556Srgrimes */ 5411556Srgrimes io_ok = 1; 5421556Srgrimes if (res != rdblksz) { 5431556Srgrimes /* 5441556Srgrimes * Record size changed. If this is happens on 5451556Srgrimes * any record after the first, we probably have 5461556Srgrimes * a tape drive which has a fixed record size 5471556Srgrimes * we are getting multiple records in a single 5481556Srgrimes * read). Watch out for record blocking that 5491556Srgrimes * violates pax spec (must be a multiple of 5501556Srgrimes * BLKMULT). 5511556Srgrimes */ 5521556Srgrimes rdblksz = res; 5531556Srgrimes if (rdblksz % BLKMULT) 5541556Srgrimes invld_rec = 1; 5551556Srgrimes } 5561556Srgrimes return(res); 5571556Srgrimes } 5581556Srgrimes break; 5591556Srgrimes case ISREG: 5601556Srgrimes case ISBLK: 5611556Srgrimes case ISCHR: 5621556Srgrimes case ISPIPE: 5631556Srgrimes default: 5641556Srgrimes /* 5651556Srgrimes * Files are so easy to deal with. These other things cannot 5661556Srgrimes * be trusted at all. So when we are dealing with character 5671556Srgrimes * devices and pipes we just take what they have ready for us 5681556Srgrimes * and return. Trying to do anything else with them runs the 5691556Srgrimes * risk of failure. 5701556Srgrimes */ 5711556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5721556Srgrimes io_ok = 1; 5731556Srgrimes return(res); 5741556Srgrimes } 5751556Srgrimes break; 5761556Srgrimes } 5771556Srgrimes 5781556Srgrimes /* 5791556Srgrimes * We are in trouble at this point, something is broken... 5801556Srgrimes */ 5811556Srgrimes lstrval = res; 5821556Srgrimes if (res < 0) 58376017Skris syswarn(1, errno, "Failed read on archive volume %d", arvol); 5841556Srgrimes else 58576017Skris paxwarn(0, "End of archive volume %d reached", arvol); 5861556Srgrimes return(res); 5878855Srgrimes} 5881556Srgrimes 5891556Srgrimes/* 5901556Srgrimes * ar_write() 5911556Srgrimes * Write a specified number of bytes in supplied buffer to the archive 5921556Srgrimes * device so it appears as a single "block". Deals with errors and tries 5931556Srgrimes * to recover when faced with short writes. 5941556Srgrimes * Return: 5951556Srgrimes * Number of bytes written. 0 indicates end of volume reached and with no 5961556Srgrimes * flaws (as best that can be detected). A -1 indicates an unrecoverable 597222177Suqs * error in the archive occurred. 5981556Srgrimes */ 5991556Srgrimes 6001556Srgrimesint 60190113Simpar_write(char *buf, int bsz) 6021556Srgrimes{ 60390113Simp int res; 6041556Srgrimes off_t cpos; 6051556Srgrimes 6061556Srgrimes /* 6071556Srgrimes * do not allow pax to create a "bad" archive. Once a write fails on 6081556Srgrimes * an archive volume prevent further writes to it. 6091556Srgrimes */ 6101556Srgrimes if (lstrval <= 0) 6111556Srgrimes return(lstrval); 6121556Srgrimes 6131556Srgrimes if ((res = write(arfd, buf, bsz)) == bsz) { 6141556Srgrimes wr_trail = 1; 6151556Srgrimes io_ok = 1; 6161556Srgrimes return(bsz); 6171556Srgrimes } 6181556Srgrimes /* 6191556Srgrimes * write broke, see what we can do with it. We try to send any partial 6201556Srgrimes * writes that may violate pax spec to the next archive volume. 6211556Srgrimes */ 6221556Srgrimes if (res < 0) 6231556Srgrimes lstrval = res; 6241556Srgrimes else 6251556Srgrimes lstrval = 0; 6261556Srgrimes 6271556Srgrimes switch (artyp) { 6281556Srgrimes case ISREG: 6291556Srgrimes if ((res > 0) && (res % BLKMULT)) { 6301556Srgrimes /* 6311556Srgrimes * try to fix up partial writes which are not BLKMULT 6321556Srgrimes * in size by forcing the runt record to next archive 6331556Srgrimes * volume 6341556Srgrimes */ 6351556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 6361556Srgrimes break; 6371556Srgrimes cpos -= (off_t)res; 6381556Srgrimes if (ftruncate(arfd, cpos) < 0) 6391556Srgrimes break; 6401556Srgrimes res = lstrval = 0; 6411556Srgrimes break; 6421556Srgrimes } 6431556Srgrimes if (res >= 0) 6441556Srgrimes break; 6451556Srgrimes /* 6461556Srgrimes * if file is out of space, handle it like a return of 0 6471556Srgrimes */ 6481556Srgrimes if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) 6491556Srgrimes res = lstrval = 0; 6501556Srgrimes break; 6511556Srgrimes case ISTAPE: 6521556Srgrimes case ISCHR: 6531556Srgrimes case ISBLK: 6541556Srgrimes if (res >= 0) 6551556Srgrimes break; 6561556Srgrimes if (errno == EACCES) { 65776017Skris paxwarn(0, "Write failed, archive is write protected."); 6581556Srgrimes res = lstrval = 0; 6591556Srgrimes return(0); 6601556Srgrimes } 6611556Srgrimes /* 6621556Srgrimes * see if we reached the end of media, if so force a change to 6631556Srgrimes * the next volume 6641556Srgrimes */ 6651556Srgrimes if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) 6661556Srgrimes res = lstrval = 0; 6671556Srgrimes break; 6681556Srgrimes case ISPIPE: 6691556Srgrimes default: 6701556Srgrimes /* 6711556Srgrimes * we cannot fix errors to these devices 6721556Srgrimes */ 6731556Srgrimes break; 6741556Srgrimes } 6751556Srgrimes 6761556Srgrimes /* 6771556Srgrimes * Better tell the user the bad news... 6781556Srgrimes * if this is a block aligned archive format, we may have a bad archive 67946684Skris * if the format wants the header to start at a BLKMULT boundary. While 6801556Srgrimes * we can deal with the mis-aligned data, it violates spec and other 681222177Suqs * archive readers will likely fail. If the format is not block 6821556Srgrimes * aligned, the user may be lucky (and the archive is ok). 6831556Srgrimes */ 6841556Srgrimes if (res >= 0) { 6851556Srgrimes if (res > 0) 6861556Srgrimes wr_trail = 1; 6871556Srgrimes io_ok = 1; 6881556Srgrimes } 6891556Srgrimes 6901556Srgrimes /* 6911556Srgrimes * If we were trying to rewrite the trailer and it didn't work, we 6921556Srgrimes * must quit right away. 6931556Srgrimes */ 6941556Srgrimes if (!wr_trail && (res <= 0)) { 69576017Skris paxwarn(1,"Unable to append, trailer re-write failed. Quitting."); 6961556Srgrimes return(res); 6971556Srgrimes } 6988855Srgrimes 6998855Srgrimes if (res == 0) 70076017Skris paxwarn(0, "End of archive volume %d reached", arvol); 7011556Srgrimes else if (res < 0) 70276017Skris syswarn(1, errno, "Failed write to archive volume: %d", arvol); 7031556Srgrimes else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0)) 70476017Skris paxwarn(0,"WARNING: partial archive write. Archive MAY BE FLAWED"); 7051556Srgrimes else 70676017Skris paxwarn(1,"WARNING: partial archive write. Archive IS FLAWED"); 7071556Srgrimes return(res); 7081556Srgrimes} 7091556Srgrimes 7101556Srgrimes/* 7111556Srgrimes * ar_rdsync() 7121556Srgrimes * Try to move past a bad spot on a flawed archive as needed to continue 7131556Srgrimes * I/O. Clears error flags to allow I/O to continue. 7141556Srgrimes * Return: 7151556Srgrimes * 0 when ok to try i/o again, -1 otherwise. 7161556Srgrimes */ 7171556Srgrimes 7181556Srgrimesint 7191556Srgrimesar_rdsync(void) 7201556Srgrimes{ 7211556Srgrimes long fsbz; 7221556Srgrimes off_t cpos; 7231556Srgrimes off_t mpos; 72476019Skris struct mtop mb; 7251556Srgrimes 7261556Srgrimes /* 7271556Srgrimes * Fail resync attempts at user request (done) or this is going to be 728108533Sschweikh * an update/append to an existing archive. If last i/o hit media end, 729108533Sschweikh * we need to go to the next volume not try a resync. 7301556Srgrimes */ 7311556Srgrimes if ((done > 0) || (lstrval == 0)) 7321556Srgrimes return(-1); 7331556Srgrimes 7341556Srgrimes if ((act == APPND) || (act == ARCHIVE)) { 73576017Skris paxwarn(1, "Cannot allow updates to an archive with flaws."); 7361556Srgrimes return(-1); 7371556Srgrimes } 7381556Srgrimes if (io_ok) 7391556Srgrimes did_io = 1; 7401556Srgrimes 7411556Srgrimes switch(artyp) { 7421556Srgrimes case ISTAPE: 7431556Srgrimes /* 7441556Srgrimes * if the last i/o was a successful data transfer, we assume 7451556Srgrimes * the fault is just a bad record on the tape that we are now 7461556Srgrimes * past. If we did not get any data since the last resync try 74746684Skris * to move the tape forward one PHYSICAL record past any 7481556Srgrimes * damaged tape section. Some tape drives are stubborn and need 7491556Srgrimes * to be pushed. 7501556Srgrimes */ 7511556Srgrimes if (io_ok) { 7521556Srgrimes io_ok = 0; 7531556Srgrimes lstrval = 1; 7541556Srgrimes break; 7551556Srgrimes } 7561556Srgrimes mb.mt_op = MTFSR; 7571556Srgrimes mb.mt_count = 1; 7581556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) 7591556Srgrimes break; 7601556Srgrimes lstrval = 1; 7611556Srgrimes break; 7621556Srgrimes case ISREG: 7631556Srgrimes case ISCHR: 7641556Srgrimes case ISBLK: 7651556Srgrimes /* 7661556Srgrimes * try to step over the bad part of the device. 7671556Srgrimes */ 7681556Srgrimes io_ok = 0; 7691556Srgrimes if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) 7701556Srgrimes fsbz = BLKMULT; 7711556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 7721556Srgrimes break; 7731556Srgrimes mpos = fsbz - (cpos % (off_t)fsbz); 7748855Srgrimes if (lseek(arfd, mpos, SEEK_CUR) < 0) 7751556Srgrimes break; 7761556Srgrimes lstrval = 1; 7771556Srgrimes break; 7781556Srgrimes case ISPIPE: 7791556Srgrimes default: 7801556Srgrimes /* 7811556Srgrimes * cannot recover on these archive device types 7821556Srgrimes */ 7831556Srgrimes io_ok = 0; 7841556Srgrimes break; 7851556Srgrimes } 7861556Srgrimes if (lstrval <= 0) { 78776017Skris paxwarn(1, "Unable to recover from an archive read failure."); 7881556Srgrimes return(-1); 7891556Srgrimes } 79076017Skris paxwarn(0, "Attempting to recover from an archive read failure."); 7911556Srgrimes return(0); 7921556Srgrimes} 7931556Srgrimes 7941556Srgrimes/* 7951556Srgrimes * ar_fow() 796222177Suqs * Move the I/O position within the archive forward the specified number of 7971556Srgrimes * bytes as supported by the device. If we cannot move the requested 7981556Srgrimes * number of bytes, return the actual number of bytes moved in skipped. 7991556Srgrimes * Return: 8001556Srgrimes * 0 if moved the requested distance, -1 on complete failure, 1 on 8011556Srgrimes * partial move (the amount moved is in skipped) 8021556Srgrimes */ 8031556Srgrimes 8041556Srgrimesint 8051556Srgrimesar_fow(off_t sksz, off_t *skipped) 8061556Srgrimes{ 8071556Srgrimes off_t cpos; 8081556Srgrimes off_t mpos; 8091556Srgrimes 8101556Srgrimes *skipped = 0; 8111556Srgrimes if (sksz <= 0) 8121556Srgrimes return(0); 8131556Srgrimes 8141556Srgrimes /* 815222177Suqs * we cannot move forward at EOF or error 8161556Srgrimes */ 8171556Srgrimes if (lstrval <= 0) 8181556Srgrimes return(lstrval); 8191556Srgrimes 8201556Srgrimes /* 8211556Srgrimes * Safer to read forward on devices where it is hard to find the end of 8221556Srgrimes * the media without reading to it. With tapes we cannot be sure of the 8231556Srgrimes * number of physical blocks to skip (we do not know physical block 824222177Suqs * size at this point), so we must only read forward on tapes! 8251556Srgrimes */ 8268855Srgrimes if (artyp != ISREG) 8271556Srgrimes return(0); 8281556Srgrimes 8291556Srgrimes /* 8301556Srgrimes * figure out where we are in the archive 8311556Srgrimes */ 8321556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) { 8338855Srgrimes /* 8341556Srgrimes * we can be asked to move farther than there are bytes in this 8351556Srgrimes * volume, if so, just go to file end and let normal buf_fill() 8361556Srgrimes * deal with the end of file (it will go to next volume by 8371556Srgrimes * itself) 8381556Srgrimes */ 8391556Srgrimes if ((mpos = cpos + sksz) > arsb.st_size) { 8401556Srgrimes *skipped = arsb.st_size - cpos; 8411556Srgrimes mpos = arsb.st_size; 8421556Srgrimes } else 8431556Srgrimes *skipped = sksz; 8441556Srgrimes if (lseek(arfd, mpos, SEEK_SET) >= 0) 8451556Srgrimes return(0); 8461556Srgrimes } 84776017Skris syswarn(1, errno, "Forward positioning operation on archive failed"); 8481556Srgrimes lstrval = -1; 8491556Srgrimes return(-1); 8501556Srgrimes} 8511556Srgrimes 8521556Srgrimes/* 8531556Srgrimes * ar_rev() 8541556Srgrimes * move the i/o position within the archive backwards the specified byte 8551556Srgrimes * count as supported by the device. With tapes drives we RESET rdblksz to 8561556Srgrimes * the PHYSICAL blocksize. 8571556Srgrimes * NOTE: We should only be called to move backwards so we can rewrite the 8581556Srgrimes * last records (the trailer) of an archive (APPEND). 8591556Srgrimes * Return: 8601556Srgrimes * 0 if moved the requested distance, -1 on complete failure 8611556Srgrimes */ 8621556Srgrimes 8631556Srgrimesint 8641556Srgrimesar_rev(off_t sksz) 8651556Srgrimes{ 8661556Srgrimes off_t cpos; 86776019Skris struct mtop mb; 86890113Simp int phyblk; 8691556Srgrimes 8701556Srgrimes /* 8711556Srgrimes * make sure we do not have try to reverse on a flawed archive 8721556Srgrimes */ 8731556Srgrimes if (lstrval < 0) 8741556Srgrimes return(lstrval); 8751556Srgrimes 8761556Srgrimes switch(artyp) { 8771556Srgrimes case ISPIPE: 8788855Srgrimes if (sksz <= 0) 8791556Srgrimes break; 8801556Srgrimes /* 8811556Srgrimes * cannot go backwards on these critters 8821556Srgrimes */ 88376017Skris paxwarn(1, "Reverse positioning on pipes is not supported."); 8841556Srgrimes lstrval = -1; 8851556Srgrimes return(-1); 8861556Srgrimes case ISREG: 8871556Srgrimes case ISBLK: 8881556Srgrimes case ISCHR: 8891556Srgrimes default: 8901556Srgrimes if (sksz <= 0) 8911556Srgrimes break; 8921556Srgrimes 8931556Srgrimes /* 8941556Srgrimes * For things other than files, backwards movement has a very 8951556Srgrimes * high probability of failure as we really do not know the 8961556Srgrimes * true attributes of the device we are talking to (the device 8971556Srgrimes * may not even have the ability to lseek() in any direction). 8981556Srgrimes * First we figure out where we are in the archive. 8991556Srgrimes */ 9001556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) { 90176017Skris syswarn(1, errno, 9021556Srgrimes "Unable to obtain current archive byte offset"); 9031556Srgrimes lstrval = -1; 9041556Srgrimes return(-1); 9051556Srgrimes } 9061556Srgrimes 9071556Srgrimes /* 9081556Srgrimes * we may try to go backwards past the start when the archive 909222177Suqs * is only a single record. If this happens and we are on a 9101556Srgrimes * multi volume archive, we need to go to the end of the 9111556Srgrimes * previous volume and continue our movement backwards from 9121556Srgrimes * there. 9131556Srgrimes */ 9141556Srgrimes if ((cpos -= sksz) < (off_t)0L) { 9151556Srgrimes if (arvol > 1) { 9161556Srgrimes /* 9171556Srgrimes * this should never happen 9181556Srgrimes */ 91976017Skris paxwarn(1,"Reverse position on previous volume."); 9201556Srgrimes lstrval = -1; 9211556Srgrimes return(-1); 9221556Srgrimes } 9231556Srgrimes cpos = (off_t)0L; 9241556Srgrimes } 9251556Srgrimes if (lseek(arfd, cpos, SEEK_SET) < 0) { 92676017Skris syswarn(1, errno, "Unable to seek archive backwards"); 9271556Srgrimes lstrval = -1; 9281556Srgrimes return(-1); 9291556Srgrimes } 9301556Srgrimes break; 9311556Srgrimes case ISTAPE: 9321556Srgrimes /* 9331556Srgrimes * Calculate and move the proper number of PHYSICAL tape 9341556Srgrimes * blocks. If the sksz is not an even multiple of the physical 9351556Srgrimes * tape size, we cannot do the move (this should never happen). 9361556Srgrimes * (We also cannot handler trailers spread over two vols). 9371556Srgrimes * get_phys() also makes sure we are in front of the filemark. 9381556Srgrimes */ 9391556Srgrimes if ((phyblk = get_phys()) <= 0) { 9401556Srgrimes lstrval = -1; 9411556Srgrimes return(-1); 9421556Srgrimes } 9431556Srgrimes 9441556Srgrimes /* 9451556Srgrimes * make sure future tape reads only go by physical tape block 9461556Srgrimes * size (set rdblksz to the real size). 9471556Srgrimes */ 9481556Srgrimes rdblksz = phyblk; 9491556Srgrimes 9501556Srgrimes /* 9511556Srgrimes * if no movement is required, just return (we must be after 9521556Srgrimes * get_phys() so the physical blocksize is properly set) 9531556Srgrimes */ 9541556Srgrimes if (sksz <= 0) 9551556Srgrimes break; 9561556Srgrimes 9571556Srgrimes /* 9581556Srgrimes * ok we have to move. Make sure the tape drive can do it. 9591556Srgrimes */ 9601556Srgrimes if (sksz % phyblk) { 96176017Skris paxwarn(1, 9621556Srgrimes "Tape drive unable to backspace requested amount"); 9631556Srgrimes lstrval = -1; 9641556Srgrimes return(-1); 9651556Srgrimes } 9661556Srgrimes 9671556Srgrimes /* 9681556Srgrimes * move backwards the requested number of bytes 9691556Srgrimes */ 9701556Srgrimes mb.mt_op = MTBSR; 9711556Srgrimes mb.mt_count = sksz/phyblk; 9721556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 97376017Skris syswarn(1,errno, "Unable to backspace tape %d blocks.", 9741556Srgrimes mb.mt_count); 9751556Srgrimes lstrval = -1; 9761556Srgrimes return(-1); 9771556Srgrimes } 9781556Srgrimes break; 9791556Srgrimes } 9801556Srgrimes lstrval = 1; 9811556Srgrimes return(0); 9821556Srgrimes} 9831556Srgrimes 9841556Srgrimes/* 9851556Srgrimes * get_phys() 9861556Srgrimes * Determine the physical block size on a tape drive. We need the physical 9878855Srgrimes * block size so we know how many bytes we skip over when we move with 9881556Srgrimes * mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when 9891556Srgrimes * return. 9901556Srgrimes * This is one really SLOW routine... 9911556Srgrimes * Return: 9921556Srgrimes * physical block size if ok (ok > 0), -1 otherwise 9931556Srgrimes */ 9941556Srgrimes 9951556Srgrimesstatic int 9961556Srgrimesget_phys(void) 9971556Srgrimes{ 99890113Simp int padsz = 0; 99990113Simp int res; 100090113Simp int phyblk; 10011556Srgrimes struct mtop mb; 10021556Srgrimes char scbuf[MAXBLK]; 10031556Srgrimes 10041556Srgrimes /* 10051556Srgrimes * move to the file mark, and then back up one record and read it. 10061556Srgrimes * this should tell us the physical record size the tape is using. 10071556Srgrimes */ 10081556Srgrimes if (lstrval == 1) { 10091556Srgrimes /* 10101556Srgrimes * we know we are at file mark when we get back a 0 from 10111556Srgrimes * read() 10121556Srgrimes */ 10131556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10141556Srgrimes padsz += res; 10151556Srgrimes if (res < 0) { 101676017Skris syswarn(1, errno, "Unable to locate tape filemark."); 10171556Srgrimes return(-1); 10181556Srgrimes } 10191556Srgrimes } 10201556Srgrimes 10211556Srgrimes /* 10221556Srgrimes * move backwards over the file mark so we are at the end of the 10231556Srgrimes * last record. 10241556Srgrimes */ 10251556Srgrimes mb.mt_op = MTBSF; 10261556Srgrimes mb.mt_count = 1; 10271556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 102876017Skris syswarn(1, errno, "Unable to backspace over tape filemark."); 10291556Srgrimes return(-1); 10301556Srgrimes } 10311556Srgrimes 10321556Srgrimes /* 10331556Srgrimes * move backwards so we are in front of the last record and read it to 10341556Srgrimes * get physical tape blocksize. 10351556Srgrimes */ 10361556Srgrimes mb.mt_op = MTBSR; 10371556Srgrimes mb.mt_count = 1; 10381556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 103976017Skris syswarn(1, errno, "Unable to backspace over last tape block."); 10401556Srgrimes return(-1); 10411556Srgrimes } 10421556Srgrimes if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) { 104376017Skris syswarn(1, errno, "Cannot determine archive tape blocksize."); 10441556Srgrimes return(-1); 10451556Srgrimes } 10461556Srgrimes 10471556Srgrimes /* 1048222177Suqs * read forward to the file mark, then back up in front of the filemark 10491556Srgrimes * (this is a bit paranoid, but should be safe to do). 10501556Srgrimes */ 10511556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10521556Srgrimes ; 10531556Srgrimes if (res < 0) { 105476017Skris syswarn(1, errno, "Unable to locate tape filemark."); 10551556Srgrimes return(-1); 10561556Srgrimes } 10571556Srgrimes mb.mt_op = MTBSF; 10581556Srgrimes mb.mt_count = 1; 10591556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 106076017Skris syswarn(1, errno, "Unable to backspace over tape filemark."); 10611556Srgrimes return(-1); 10621556Srgrimes } 10631556Srgrimes 10641556Srgrimes /* 10651556Srgrimes * set lstrval so we know that the filemark has not been seen 10661556Srgrimes */ 10671556Srgrimes lstrval = 1; 10681556Srgrimes 10691556Srgrimes /* 10701556Srgrimes * return if there was no padding 10711556Srgrimes */ 10721556Srgrimes if (padsz == 0) 10731556Srgrimes return(phyblk); 10741556Srgrimes 10751556Srgrimes /* 10761556Srgrimes * make sure we can move backwards over the padding. (this should 10771556Srgrimes * never fail). 10781556Srgrimes */ 10791556Srgrimes if (padsz % phyblk) { 108076017Skris paxwarn(1, "Tape drive unable to backspace requested amount"); 10811556Srgrimes return(-1); 10821556Srgrimes } 10831556Srgrimes 10841556Srgrimes /* 10851556Srgrimes * move backwards over the padding so the head is where it was when 10861556Srgrimes * we were first called (if required). 10871556Srgrimes */ 10881556Srgrimes mb.mt_op = MTBSR; 10891556Srgrimes mb.mt_count = padsz/phyblk; 10901556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 109176017Skris syswarn(1,errno,"Unable to backspace tape over %d pad blocks", 10921556Srgrimes mb.mt_count); 10931556Srgrimes return(-1); 10941556Srgrimes } 10951556Srgrimes return(phyblk); 10961556Srgrimes} 10971556Srgrimes 10981556Srgrimes/* 10991556Srgrimes * ar_next() 11001556Srgrimes * prompts the user for the next volume in this archive. For some devices 11011556Srgrimes * we may allow the media to be changed. Otherwise a new archive is 11021556Srgrimes * prompted for. By pax spec, if there is no controlling tty or an eof is 11031556Srgrimes * read on tty input, we must quit pax. 11041556Srgrimes * Return: 11051556Srgrimes * 0 when ready to continue, -1 when all done 11061556Srgrimes */ 11071556Srgrimes 11081556Srgrimesint 11091556Srgrimesar_next(void) 11101556Srgrimes{ 1111169993Sbrian static char *arcbuf; 11121556Srgrimes char buf[PAXPATHLEN+2]; 11131556Srgrimes sigset_t o_mask; 11141556Srgrimes 11151556Srgrimes /* 11161556Srgrimes * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so 11171556Srgrimes * things like writing EOF etc will be done) (Watch out ar_close() can 11181556Srgrimes * also be called via a signal handler, so we must prevent a race. 11191556Srgrimes */ 11201556Srgrimes if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0) 112176017Skris syswarn(0, errno, "Unable to set signal mask"); 11221556Srgrimes ar_close(); 112376017Skris if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0) 112476017Skris syswarn(0, errno, "Unable to restore signal mask"); 11251556Srgrimes 112676351Skris if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0) 11271556Srgrimes return(-1); 11281556Srgrimes 11291556Srgrimes tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0); 11301556Srgrimes 11311556Srgrimes /* 11321556Srgrimes * if i/o is on stdin or stdout, we cannot reopen it (we do not know 11331556Srgrimes * the name), the user will be forced to type it in. 11341556Srgrimes */ 1135114583Smarkm if (strcmp(arcname, stdo) && strcmp(arcname, stdn) && (artyp != ISREG) 11361556Srgrimes && (artyp != ISPIPE)) { 11371556Srgrimes if (artyp == ISTAPE) { 11381556Srgrimes tty_prnt("%s ready for archive tape volume: %d\n", 11391556Srgrimes arcname, arvol); 11401556Srgrimes tty_prnt("Load the NEXT TAPE on the tape drive"); 11411556Srgrimes } else { 11421556Srgrimes tty_prnt("%s ready for archive volume: %d\n", 11431556Srgrimes arcname, arvol); 11441556Srgrimes tty_prnt("Load the NEXT STORAGE MEDIA (if required)"); 11451556Srgrimes } 11461556Srgrimes 11471556Srgrimes if ((act == ARCHIVE) || (act == APPND)) 11481556Srgrimes tty_prnt(" and make sure it is WRITE ENABLED.\n"); 11491556Srgrimes else 11501556Srgrimes tty_prnt("\n"); 11511556Srgrimes 11521556Srgrimes for(;;) { 11531556Srgrimes tty_prnt("Type \"y\" to continue, \".\" to quit %s,", 11541556Srgrimes argv0); 11551556Srgrimes tty_prnt(" or \"s\" to switch to new device.\nIf you"); 11561556Srgrimes tty_prnt(" cannot change storage media, type \"s\"\n"); 11571556Srgrimes tty_prnt("Is the device ready and online? > "); 11581556Srgrimes 11591556Srgrimes if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){ 11601556Srgrimes done = 1; 11611556Srgrimes lstrval = -1; 11621556Srgrimes tty_prnt("Quitting %s!\n", argv0); 11631556Srgrimes vfpart = 0; 11641556Srgrimes return(-1); 11651556Srgrimes } 11661556Srgrimes 11671556Srgrimes if ((buf[0] == '\0') || (buf[1] != '\0')) { 11681556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 11691556Srgrimes continue; 11701556Srgrimes } 11711556Srgrimes 11721556Srgrimes switch (buf[0]) { 11731556Srgrimes case 'y': 11741556Srgrimes case 'Y': 11751556Srgrimes /* 11761556Srgrimes * we are to continue with the same device 11771556Srgrimes */ 11788855Srgrimes if (ar_open(arcname) >= 0) 11791556Srgrimes return(0); 11801556Srgrimes tty_prnt("Cannot re-open %s, try again\n", 11811556Srgrimes arcname); 11821556Srgrimes continue; 11831556Srgrimes case 's': 11841556Srgrimes case 'S': 11851556Srgrimes /* 11861556Srgrimes * user wants to open a different device 11871556Srgrimes */ 11881556Srgrimes tty_prnt("Switching to a different archive\n"); 11891556Srgrimes break; 11901556Srgrimes default: 11911556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 11921556Srgrimes continue; 11931556Srgrimes } 11941556Srgrimes break; 11951556Srgrimes } 11961556Srgrimes } else 11971556Srgrimes tty_prnt("Ready for archive volume: %d\n", arvol); 11981556Srgrimes 11991556Srgrimes /* 12001556Srgrimes * have to go to a different archive 12011556Srgrimes */ 12021556Srgrimes for (;;) { 12031556Srgrimes tty_prnt("Input archive name or \".\" to quit %s.\n", argv0); 12041556Srgrimes tty_prnt("Archive name > "); 12051556Srgrimes 12061556Srgrimes if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) { 12071556Srgrimes done = 1; 12081556Srgrimes lstrval = -1; 12091556Srgrimes tty_prnt("Quitting %s!\n", argv0); 12101556Srgrimes vfpart = 0; 12111556Srgrimes return(-1); 12121556Srgrimes } 12131556Srgrimes if (buf[0] == '\0') { 12141556Srgrimes tty_prnt("Empty file name, try again\n"); 12151556Srgrimes continue; 12161556Srgrimes } 121776019Skris if (!strcmp(buf, "..")) { 121876019Skris tty_prnt("Illegal file name: .. try again\n"); 121976019Skris continue; 122076019Skris } 12211556Srgrimes if (strlen(buf) > PAXPATHLEN) { 12221556Srgrimes tty_prnt("File name too long, try again\n"); 12231556Srgrimes continue; 12241556Srgrimes } 12251556Srgrimes 12261556Srgrimes /* 12271556Srgrimes * try to open new archive 12281556Srgrimes */ 12291556Srgrimes if (ar_open(buf) >= 0) { 1230169993Sbrian free(arcbuf); 1231169993Sbrian if ((arcbuf = strdup(buf)) == NULL) { 12321556Srgrimes done = 1; 12331556Srgrimes lstrval = -1; 123476017Skris paxwarn(0, "Cannot save archive name."); 12351556Srgrimes return(-1); 12361556Srgrimes } 1237169993Sbrian arcname = arcbuf; 12381556Srgrimes break; 12391556Srgrimes } 12401556Srgrimes tty_prnt("Cannot open %s, try again\n", buf); 12411556Srgrimes continue; 12421556Srgrimes } 12431556Srgrimes return(0); 12441556Srgrimes} 124576286Skris 124676286Skris/* 124776286Skris * ar_start_gzip() 124876286Skris * starts the gzip compression/decompression process as a child, using magic 124976286Skris * to keep the fd the same in the calling function (parent). 125076286Skris */ 125176286Skrisvoid 1252114583Smarkmar_start_gzip(int fd, const char *gzip_prog, int wr) 125376286Skris{ 125476286Skris int fds[2]; 1255114583Smarkm const char *gzip_flags; 125676286Skris 125776286Skris if (pipe(fds) < 0) 125876286Skris err(1, "could not pipe"); 125976286Skris zpid = fork(); 126076286Skris if (zpid < 0) 126176286Skris err(1, "could not fork"); 126276286Skris 126376286Skris /* parent */ 126476286Skris if (zpid) { 126576286Skris if (wr) 126676286Skris dup2(fds[1], fd); 126776286Skris else 126876286Skris dup2(fds[0], fd); 126976286Skris close(fds[0]); 127076286Skris close(fds[1]); 127176286Skris } else { 127276286Skris if (wr) { 127376286Skris dup2(fds[0], STDIN_FILENO); 127476286Skris dup2(fd, STDOUT_FILENO); 127576286Skris gzip_flags = "-c"; 127676286Skris } else { 127776286Skris dup2(fds[1], STDOUT_FILENO); 127876286Skris dup2(fd, STDIN_FILENO); 127976286Skris gzip_flags = "-dc"; 128076286Skris } 128176286Skris close(fds[0]); 128276286Skris close(fds[1]); 1283114583Smarkm if (execlp(gzip_prog, gzip_prog, gzip_flags, 128479452Sbrian (char *)NULL) < 0) 128576286Skris err(1, "could not exec"); 128676286Skris /* NOTREACHED */ 128776286Skris } 128876286Skris} 1289