ar_io.c revision 114583
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 * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 361556Srgrimes */ 371556Srgrimes 381556Srgrimes#ifndef lint 3936049Scharnier#if 0 4036049Scharnierstatic char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; 4136049Scharnier#endif 421556Srgrimes#endif /* not lint */ 4399110Sobrien#include <sys/cdefs.h> 4499110Sobrien__FBSDID("$FreeBSD: head/bin/pax/ar_io.c 114583 2003-05-03 16:39:34Z markm $"); 451556Srgrimes 461556Srgrimes#include <sys/types.h> 471556Srgrimes#include <sys/ioctl.h> 481556Srgrimes#include <sys/mtio.h> 4976286Skris#include <sys/stat.h> 5076286Skris#include <sys/wait.h> 5176286Skris#include <err.h> 5276286Skris#include <errno.h> 5376286Skris#include <fcntl.h> 541556Srgrimes#include <signal.h> 55104548Stjr#include <stdint.h> 5676286Skris#include <stdio.h> 571556Srgrimes#include <string.h> 5876286Skris#include <stdlib.h> 591556Srgrimes#include <unistd.h> 601556Srgrimes#include "pax.h" 6176351Skris#include "options.h" 621556Srgrimes#include "extern.h" 631556Srgrimes 641556Srgrimes/* 651556Srgrimes * Routines which deal directly with the archive I/O device/file. 661556Srgrimes */ 671556Srgrimes 681556Srgrimes#define DMOD 0666 /* default mode of created archives */ 691556Srgrimes#define EXT_MODE O_RDONLY /* open mode for list/extract */ 701556Srgrimes#define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */ 711556Srgrimes#define APP_MODE O_RDWR /* mode for append */ 72114583Smarkm 73114583Smarkmstatic char none[] = "<NONE>"; /* pseudo name for no file */ 74114583Smarkmstatic char stdo[] = "<STDOUT>"; /* pseudo name for stdout */ 75114583Smarkmstatic char stdn[] = "<STDIN>"; /* pseudo name for stdin */ 761556Srgrimesstatic int arfd = -1; /* archive file descriptor */ 771556Srgrimesstatic int artyp = ISREG; /* archive type: file/FIFO/tape */ 781556Srgrimesstatic int arvol = 1; /* archive volume number */ 791556Srgrimesstatic int lstrval = -1; /* return value from last i/o */ 801556Srgrimesstatic int io_ok; /* i/o worked on volume after resync */ 811556Srgrimesstatic int did_io; /* did i/o ever occur on volume? */ 821556Srgrimesstatic int done; /* set via tty termination */ 831556Srgrimesstatic struct stat arsb; /* stat of archive device at open */ 841556Srgrimesstatic int invld_rec; /* tape has out of spec record size */ 851556Srgrimesstatic int wr_trail = 1; /* trailer was rewritten in append */ 861556Srgrimesstatic int can_unlnk = 0; /* do we unlink null archives? */ 87114583Smarkmconst char *arcname; /* printable name of archive */ 8876286Skrisconst char *gzip_program; /* name of gzip program */ 8976286Skrisstatic pid_t zpid = -1; /* pid of child process */ 901556Srgrimes 9190110Simpstatic int get_phys(void); 921556Srgrimesextern sigset_t s_mask; 9390110Simpstatic void ar_start_gzip(int, const char *, int); 941556Srgrimes 951556Srgrimes/* 961556Srgrimes * ar_open() 971556Srgrimes * Opens the next archive volume. Determines the type of the device and 981556Srgrimes * sets up block sizes as required by the archive device and the format. 991556Srgrimes * Note: we may be called with name == NULL on the first open only. 1001556Srgrimes * Return: 1011556Srgrimes * -1 on failure, 0 otherwise 1021556Srgrimes */ 1031556Srgrimes 1041556Srgrimesint 105114583Smarkmar_open(const char *name) 1061556Srgrimes{ 10776019Skris struct mtget mb; 1081556Srgrimes 1091556Srgrimes if (arfd != -1) 1101556Srgrimes (void)close(arfd); 1111556Srgrimes arfd = -1; 1121556Srgrimes can_unlnk = did_io = io_ok = invld_rec = 0; 1131556Srgrimes artyp = ISREG; 1141556Srgrimes flcnt = 0; 1151556Srgrimes 1161556Srgrimes /* 1171556Srgrimes * open based on overall operation mode 1181556Srgrimes */ 1191556Srgrimes switch (act) { 1201556Srgrimes case LIST: 1211556Srgrimes case EXTRACT: 1221556Srgrimes if (name == NULL) { 1231556Srgrimes arfd = STDIN_FILENO; 124114583Smarkm arcname = stdn; 1251556Srgrimes } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) 12676017Skris syswarn(0, errno, "Failed open to read on %s", name); 12776286Skris if (arfd != -1 && gzip_program != NULL) 12876286Skris ar_start_gzip(arfd, gzip_program, 0); 1291556Srgrimes break; 1301556Srgrimes case ARCHIVE: 1311556Srgrimes if (name == NULL) { 1321556Srgrimes arfd = STDOUT_FILENO; 133114583Smarkm arcname = stdo; 1341556Srgrimes } else if ((arfd = open(name, AR_MODE, DMOD)) < 0) 13576017Skris syswarn(0, errno, "Failed open to write on %s", name); 1361556Srgrimes else 1371556Srgrimes can_unlnk = 1; 13876286Skris if (arfd != -1 && gzip_program != NULL) 13976286Skris ar_start_gzip(arfd, gzip_program, 1); 1401556Srgrimes break; 1411556Srgrimes case APPND: 1421556Srgrimes if (name == NULL) { 1431556Srgrimes arfd = STDOUT_FILENO; 144114583Smarkm arcname = stdo; 1451556Srgrimes } else if ((arfd = open(name, APP_MODE, DMOD)) < 0) 14676017Skris syswarn(0, errno, "Failed open to read/write on %s", 1471556Srgrimes name); 1481556Srgrimes break; 1491556Srgrimes case COPY: 1501556Srgrimes /* 1511556Srgrimes * arfd not used in COPY mode 1521556Srgrimes */ 153114583Smarkm arcname = none; 1541556Srgrimes lstrval = 1; 1551556Srgrimes return(0); 1561556Srgrimes } 1571556Srgrimes if (arfd < 0) 1581556Srgrimes return(-1); 1591556Srgrimes 16076351Skris if (chdname != NULL) 16176351Skris if (chdir(chdname) != 0) 16276351Skris syswarn(1, errno, "Failed chdir to %s", chdname); 1631556Srgrimes /* 1641556Srgrimes * set up is based on device type 1651556Srgrimes */ 1661556Srgrimes if (fstat(arfd, &arsb) < 0) { 16776017Skris syswarn(0, errno, "Failed stat on %s", arcname); 1681556Srgrimes (void)close(arfd); 1691556Srgrimes arfd = -1; 1701556Srgrimes can_unlnk = 0; 1711556Srgrimes return(-1); 1721556Srgrimes } 1731556Srgrimes if (S_ISDIR(arsb.st_mode)) { 17476017Skris paxwarn(0, "Cannot write an archive on top of a directory %s", 1751556Srgrimes arcname); 1761556Srgrimes (void)close(arfd); 1771556Srgrimes arfd = -1; 1781556Srgrimes can_unlnk = 0; 1791556Srgrimes return(-1); 1801556Srgrimes } 1811556Srgrimes 1821556Srgrimes if (S_ISCHR(arsb.st_mode)) 1831556Srgrimes artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; 1841556Srgrimes else if (S_ISBLK(arsb.st_mode)) 1851556Srgrimes artyp = ISBLK; 1861556Srgrimes else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) 1871556Srgrimes artyp = ISPIPE; 1881556Srgrimes else 1891556Srgrimes artyp = ISREG; 1901556Srgrimes 1911556Srgrimes /* 1921556Srgrimes * make sure we beyond any doubt that we only can unlink regular files 1931556Srgrimes * we created 1941556Srgrimes */ 1951556Srgrimes if (artyp != ISREG) 1961556Srgrimes can_unlnk = 0; 1971556Srgrimes /* 1981556Srgrimes * if we are writing, we are done 1991556Srgrimes */ 2001556Srgrimes if (act == ARCHIVE) { 2011556Srgrimes blksz = rdblksz = wrblksz; 2021556Srgrimes lstrval = 1; 2031556Srgrimes return(0); 2041556Srgrimes } 2051556Srgrimes 2061556Srgrimes /* 2071556Srgrimes * set default blksz on read. APPNDs writes rdblksz on the last volume 2081556Srgrimes * On all new archive volumes, we shift to wrblksz (if the user 2091556Srgrimes * specified one, otherwize we will continue to use rdblksz). We 2101556Srgrimes * must to set blocksize based on what kind of device the archive is 2111556Srgrimes * stored. 2121556Srgrimes */ 2131556Srgrimes switch(artyp) { 2141556Srgrimes case ISTAPE: 2151556Srgrimes /* 2161556Srgrimes * Tape drives come in at least two flavors. Those that support 2171556Srgrimes * variable sized records and those that have fixed sized 2181556Srgrimes * records. They must be treated differently. For tape drives 2191556Srgrimes * that support variable sized records, we must make large 2201556Srgrimes * reads to make sure we get the entire record, otherwise we 2211556Srgrimes * will just get the first part of the record (up to size we 2221556Srgrimes * asked). Tapes with fixed sized records may or may not return 2231556Srgrimes * multiple records in a single read. We really do not care 2241556Srgrimes * what the physical record size is UNLESS we are going to 2251556Srgrimes * append. (We will need the physical block size to rewrite 2261556Srgrimes * the trailer). Only when we are appending do we go to the 2271556Srgrimes * effort to figure out the true PHYSICAL record size. 2281556Srgrimes */ 2291556Srgrimes blksz = rdblksz = MAXBLK; 2301556Srgrimes break; 2311556Srgrimes case ISPIPE: 2321556Srgrimes case ISBLK: 2331556Srgrimes case ISCHR: 2341556Srgrimes /* 2351556Srgrimes * Blocksize is not a major issue with these devices (but must 2361556Srgrimes * be kept a multiple of 512). If the user specified a write 2371556Srgrimes * block size, we use that to read. Under append, we must 2381556Srgrimes * always keep blksz == rdblksz. Otherwise we go ahead and use 2391556Srgrimes * the device optimal blocksize as (and if) returned by stat 2401556Srgrimes * and if it is within pax specs. 2411556Srgrimes */ 2421556Srgrimes if ((act == APPND) && wrblksz) { 2431556Srgrimes blksz = rdblksz = wrblksz; 2441556Srgrimes break; 2451556Srgrimes } 2461556Srgrimes 2471556Srgrimes if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && 2481556Srgrimes ((arsb.st_blksize % BLKMULT) == 0)) 2491556Srgrimes rdblksz = arsb.st_blksize; 2501556Srgrimes else 2511556Srgrimes rdblksz = DEVBLK; 2521556Srgrimes /* 2531556Srgrimes * For performance go for large reads when we can without harm 2541556Srgrimes */ 2551556Srgrimes if ((act == APPND) || (artyp == ISCHR)) 2561556Srgrimes blksz = rdblksz; 2571556Srgrimes else 2581556Srgrimes blksz = MAXBLK; 2591556Srgrimes break; 2601556Srgrimes case ISREG: 2611556Srgrimes /* 2621556Srgrimes * if the user specified wrblksz works, use it. Under appends 2631556Srgrimes * we must always keep blksz == rdblksz 2641556Srgrimes */ 2651556Srgrimes if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ 2661556Srgrimes blksz = rdblksz = wrblksz; 2671556Srgrimes break; 2681556Srgrimes } 2691556Srgrimes /* 2701556Srgrimes * See if we can find the blocking factor from the file size 2711556Srgrimes */ 2721556Srgrimes for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) 2731556Srgrimes if ((arsb.st_size % rdblksz) == 0) 2741556Srgrimes break; 2751556Srgrimes /* 27646684Skris * When we cannot find a match, we may have a flawed archive. 2771556Srgrimes */ 2781556Srgrimes if (rdblksz <= 0) 2791556Srgrimes rdblksz = FILEBLK; 2801556Srgrimes /* 2811556Srgrimes * for performance go for large reads when we can 2821556Srgrimes */ 2831556Srgrimes if (act == APPND) 2841556Srgrimes blksz = rdblksz; 2851556Srgrimes else 2861556Srgrimes blksz = MAXBLK; 2871556Srgrimes break; 2881556Srgrimes default: 2891556Srgrimes /* 2908855Srgrimes * should never happen, worse case, slow... 2911556Srgrimes */ 2921556Srgrimes blksz = rdblksz = BLKMULT; 2931556Srgrimes break; 2941556Srgrimes } 2951556Srgrimes lstrval = 1; 2961556Srgrimes return(0); 2971556Srgrimes} 2981556Srgrimes 2991556Srgrimes/* 3001556Srgrimes * ar_close() 3011556Srgrimes * closes archive device, increments volume number, and prints i/o summary 3021556Srgrimes */ 3031556Srgrimesvoid 3041556Srgrimesar_close(void) 3051556Srgrimes{ 3061556Srgrimes 3071556Srgrimes if (arfd < 0) { 3081556Srgrimes did_io = io_ok = flcnt = 0; 3091556Srgrimes return; 3101556Srgrimes } 3111556Srgrimes 3121556Srgrimes /* 3131556Srgrimes * Close archive file. This may take a LONG while on tapes (we may be 3141556Srgrimes * forced to wait for the rewind to complete) so tell the user what is 3151556Srgrimes * going on (this avoids the user hitting control-c thinking pax is 3161556Srgrimes * broken). 3171556Srgrimes */ 3181556Srgrimes if (vflag && (artyp == ISTAPE)) { 3191556Srgrimes if (vfpart) 32076351Skris (void)putc('\n', listf); 32176351Skris (void)fprintf(listf, 3221556Srgrimes "%s: Waiting for tape drive close to complete...", 3231556Srgrimes argv0); 32476351Skris (void)fflush(listf); 3251556Srgrimes } 3261556Srgrimes 3271556Srgrimes /* 3281556Srgrimes * if nothing was written to the archive (and we created it), we remove 3291556Srgrimes * it 3301556Srgrimes */ 3311556Srgrimes if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && 3321556Srgrimes (arsb.st_size == 0)) { 3331556Srgrimes (void)unlink(arcname); 3341556Srgrimes can_unlnk = 0; 3351556Srgrimes } 3361556Srgrimes 33776286Skris /* 33876286Skris * for a quick extract/list, pax frequently exits before the child 33976286Skris * process is done 34076286Skris */ 34176286Skris if ((act == LIST || act == EXTRACT) && nflag && zpid > 0) { 34276286Skris int status; 34376286Skris kill(zpid, SIGINT); 34476286Skris waitpid(zpid, &status, 0); 34576286Skris } 34676286Skris 3471556Srgrimes (void)close(arfd); 3481556Srgrimes 3491556Srgrimes if (vflag && (artyp == ISTAPE)) { 35076351Skris (void)fputs("done.\n", listf); 3511556Srgrimes vfpart = 0; 35276351Skris (void)fflush(listf); 3531556Srgrimes } 3541556Srgrimes arfd = -1; 3551556Srgrimes 3561556Srgrimes if (!io_ok && !did_io) { 3571556Srgrimes flcnt = 0; 3581556Srgrimes return; 3591556Srgrimes } 3601556Srgrimes did_io = io_ok = 0; 3611556Srgrimes 3621556Srgrimes /* 3631556Srgrimes * The volume number is only increased when the last device has data 3641556Srgrimes * and we have already determined the archive format. 3651556Srgrimes */ 3661556Srgrimes if (frmt != NULL) 3671556Srgrimes ++arvol; 3681556Srgrimes 3691556Srgrimes if (!vflag) { 3701556Srgrimes flcnt = 0; 3711556Srgrimes return; 3721556Srgrimes } 3731556Srgrimes 3741556Srgrimes /* 3751556Srgrimes * Print out a summary of I/O for this archive volume. 3761556Srgrimes */ 3771556Srgrimes if (vfpart) { 37876351Skris (void)putc('\n', listf); 3791556Srgrimes vfpart = 0; 3801556Srgrimes } 3811556Srgrimes 3821556Srgrimes /* 3831556Srgrimes * If we have not determined the format yet, we just say how many bytes 3841556Srgrimes * we have skipped over looking for a header to id. there is no way we 3851556Srgrimes * could have written anything yet. 3861556Srgrimes */ 3871556Srgrimes if (frmt == NULL) { 3881556Srgrimes# ifdef NET2_STAT 38976351Skris (void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n", 390104548Stjr argv0, rdcnt); 3911556Srgrimes# else 392104548Stjr (void)fprintf(listf, "%s: unknown format, %ju bytes skipped.\n", 393104548Stjr argv0, (uintmax_t)rdcnt); 3941556Srgrimes# endif 39576351Skris (void)fflush(listf); 3961556Srgrimes flcnt = 0; 3971556Srgrimes return; 3981556Srgrimes } 3991556Srgrimes 40076351Skris if (strcmp(NM_CPIO, argv0) == 0) 401104548Stjr (void)fprintf(listf, "%llu blocks\n", 402104548Stjr (unsigned long long)((rdcnt ? rdcnt : wrcnt) / 5120)); 40376351Skris else if (strcmp(NM_TAR, argv0) != 0) 40476351Skris (void)fprintf(listf, 4051556Srgrimes# ifdef NET2_STAT 40676019Skris "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n", 407104548Stjr argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt); 4081556Srgrimes# else 409104548Stjr "%s: %s vol %d, %ju files, %ju bytes read, %ju bytes written.\n", 410104548Stjr argv0, frmt->name, arvol-1, (uintmax_t)flcnt, 411104548Stjr (uintmax_t)rdcnt, (uintmax_t)wrcnt); 4121556Srgrimes# endif 41376351Skris (void)fflush(listf); 4141556Srgrimes flcnt = 0; 4151556Srgrimes} 4161556Srgrimes 4171556Srgrimes/* 4181556Srgrimes * ar_drain() 4191556Srgrimes * drain any archive format independent padding from an archive read 4201556Srgrimes * from a socket or a pipe. This is to prevent the process on the 4211556Srgrimes * other side of the pipe from getting a SIGPIPE (pax will stop 4221556Srgrimes * reading an archive once a format dependent trailer is detected). 4231556Srgrimes */ 4241556Srgrimesvoid 4251556Srgrimesar_drain(void) 4261556Srgrimes{ 42790113Simp int res; 4281556Srgrimes char drbuf[MAXBLK]; 4291556Srgrimes 4301556Srgrimes /* 4311556Srgrimes * we only drain from a pipe/socket. Other devices can be closed 4321556Srgrimes * without reading up to end of file. We sure hope that pipe is closed 4331556Srgrimes * on the other side so we will get an EOF. 4341556Srgrimes */ 4351556Srgrimes if ((artyp != ISPIPE) || (lstrval <= 0)) 4361556Srgrimes return; 4371556Srgrimes 4381556Srgrimes /* 4391556Srgrimes * keep reading until pipe is drained 4401556Srgrimes */ 4411556Srgrimes while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) 4421556Srgrimes ; 4431556Srgrimes lstrval = res; 4441556Srgrimes} 4451556Srgrimes 4461556Srgrimes/* 4471556Srgrimes * ar_set_wr() 4481556Srgrimes * Set up device right before switching from read to write in an append. 4491556Srgrimes * device dependent code (if required) to do this should be added here. 4501556Srgrimes * For all archive devices we are already positioned at the place we want 4511556Srgrimes * to start writing when this routine is called. 4521556Srgrimes * Return: 4531556Srgrimes * 0 if all ready to write, -1 otherwise 4541556Srgrimes */ 4551556Srgrimes 4561556Srgrimesint 4571556Srgrimesar_set_wr(void) 4581556Srgrimes{ 4591556Srgrimes off_t cpos; 4601556Srgrimes 4611556Srgrimes /* 4621556Srgrimes * we must make sure the trailer is rewritten on append, ar_next() 4631556Srgrimes * will stop us if the archive containing the trailer was not written 4641556Srgrimes */ 4651556Srgrimes wr_trail = 0; 4668855Srgrimes 4678855Srgrimes /* 4681556Srgrimes * Add any device dependent code as required here 4691556Srgrimes */ 4701556Srgrimes if (artyp != ISREG) 4711556Srgrimes return(0); 4721556Srgrimes /* 4731556Srgrimes * Ok we have an archive in a regular file. If we were rewriting a 4741556Srgrimes * file, we must get rid of all the stuff after the current offset 4751556Srgrimes * (it was not written by pax). 4761556Srgrimes */ 4771556Srgrimes if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) || 4781556Srgrimes (ftruncate(arfd, cpos) < 0)) { 47976017Skris syswarn(1, errno, "Unable to truncate archive file"); 4801556Srgrimes return(-1); 4811556Srgrimes } 4821556Srgrimes return(0); 4831556Srgrimes} 4841556Srgrimes 4851556Srgrimes/* 4861556Srgrimes * ar_app_ok() 4871556Srgrimes * check if the last volume in the archive allows appends. We cannot check 4888855Srgrimes * this until we are ready to write since there is no spec that says all 4891556Srgrimes * volumes in a single archive have to be of the same type... 4901556Srgrimes * Return: 4911556Srgrimes * 0 if we can append, -1 otherwise. 4921556Srgrimes */ 4931556Srgrimes 4941556Srgrimesint 4951556Srgrimesar_app_ok(void) 4961556Srgrimes{ 4971556Srgrimes if (artyp == ISPIPE) { 49876017Skris paxwarn(1, "Cannot append to an archive obtained from a pipe."); 4991556Srgrimes return(-1); 5001556Srgrimes } 5011556Srgrimes 5021556Srgrimes if (!invld_rec) 5031556Srgrimes return(0); 50476017Skris paxwarn(1,"Cannot append, device record size %d does not support %s spec", 5051556Srgrimes rdblksz, argv0); 5061556Srgrimes return(-1); 5071556Srgrimes} 5081556Srgrimes 5091556Srgrimes/* 5101556Srgrimes * ar_read() 5111556Srgrimes * read up to a specified number of bytes from the archive into the 5121556Srgrimes * supplied buffer. When dealing with tapes we may not always be able to 5131556Srgrimes * read what we want. 5141556Srgrimes * Return: 5151556Srgrimes * Number of bytes in buffer. 0 for end of file, -1 for a read error. 5161556Srgrimes */ 5171556Srgrimes 5181556Srgrimesint 51990113Simpar_read(char *buf, int cnt) 5201556Srgrimes{ 52190113Simp int res = 0; 5221556Srgrimes 5231556Srgrimes /* 5241556Srgrimes * if last i/o was in error, no more reads until reset or new volume 5251556Srgrimes */ 5261556Srgrimes if (lstrval <= 0) 5271556Srgrimes return(lstrval); 5281556Srgrimes 5291556Srgrimes /* 5301556Srgrimes * how we read must be based on device type 5311556Srgrimes */ 5321556Srgrimes switch (artyp) { 5331556Srgrimes case ISTAPE: 5341556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5351556Srgrimes /* 5361556Srgrimes * CAUTION: tape systems may not always return the same 5371556Srgrimes * sized records so we leave blksz == MAXBLK. The 5381556Srgrimes * physical record size that a tape drive supports is 5391556Srgrimes * very hard to determine in a uniform and portable 5401556Srgrimes * manner. 5411556Srgrimes */ 5421556Srgrimes io_ok = 1; 5431556Srgrimes if (res != rdblksz) { 5441556Srgrimes /* 5451556Srgrimes * Record size changed. If this is happens on 5461556Srgrimes * any record after the first, we probably have 5471556Srgrimes * a tape drive which has a fixed record size 5481556Srgrimes * we are getting multiple records in a single 5491556Srgrimes * read). Watch out for record blocking that 5501556Srgrimes * violates pax spec (must be a multiple of 5511556Srgrimes * BLKMULT). 5521556Srgrimes */ 5531556Srgrimes rdblksz = res; 5541556Srgrimes if (rdblksz % BLKMULT) 5551556Srgrimes invld_rec = 1; 5561556Srgrimes } 5571556Srgrimes return(res); 5581556Srgrimes } 5591556Srgrimes break; 5601556Srgrimes case ISREG: 5611556Srgrimes case ISBLK: 5621556Srgrimes case ISCHR: 5631556Srgrimes case ISPIPE: 5641556Srgrimes default: 5651556Srgrimes /* 5661556Srgrimes * Files are so easy to deal with. These other things cannot 5671556Srgrimes * be trusted at all. So when we are dealing with character 5681556Srgrimes * devices and pipes we just take what they have ready for us 5691556Srgrimes * and return. Trying to do anything else with them runs the 5701556Srgrimes * risk of failure. 5711556Srgrimes */ 5721556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5731556Srgrimes io_ok = 1; 5741556Srgrimes return(res); 5751556Srgrimes } 5761556Srgrimes break; 5771556Srgrimes } 5781556Srgrimes 5791556Srgrimes /* 5801556Srgrimes * We are in trouble at this point, something is broken... 5811556Srgrimes */ 5821556Srgrimes lstrval = res; 5831556Srgrimes if (res < 0) 58476017Skris syswarn(1, errno, "Failed read on archive volume %d", arvol); 5851556Srgrimes else 58676017Skris paxwarn(0, "End of archive volume %d reached", arvol); 5871556Srgrimes return(res); 5888855Srgrimes} 5891556Srgrimes 5901556Srgrimes/* 5911556Srgrimes * ar_write() 5921556Srgrimes * Write a specified number of bytes in supplied buffer to the archive 5931556Srgrimes * device so it appears as a single "block". Deals with errors and tries 5941556Srgrimes * to recover when faced with short writes. 5951556Srgrimes * Return: 5961556Srgrimes * Number of bytes written. 0 indicates end of volume reached and with no 5971556Srgrimes * flaws (as best that can be detected). A -1 indicates an unrecoverable 5981556Srgrimes * error in the archive occured. 5991556Srgrimes */ 6001556Srgrimes 6011556Srgrimesint 60290113Simpar_write(char *buf, int bsz) 6031556Srgrimes{ 60490113Simp int res; 6051556Srgrimes off_t cpos; 6061556Srgrimes 6071556Srgrimes /* 6081556Srgrimes * do not allow pax to create a "bad" archive. Once a write fails on 6091556Srgrimes * an archive volume prevent further writes to it. 6101556Srgrimes */ 6111556Srgrimes if (lstrval <= 0) 6121556Srgrimes return(lstrval); 6131556Srgrimes 6141556Srgrimes if ((res = write(arfd, buf, bsz)) == bsz) { 6151556Srgrimes wr_trail = 1; 6161556Srgrimes io_ok = 1; 6171556Srgrimes return(bsz); 6181556Srgrimes } 6191556Srgrimes /* 6201556Srgrimes * write broke, see what we can do with it. We try to send any partial 6211556Srgrimes * writes that may violate pax spec to the next archive volume. 6221556Srgrimes */ 6231556Srgrimes if (res < 0) 6241556Srgrimes lstrval = res; 6251556Srgrimes else 6261556Srgrimes lstrval = 0; 6271556Srgrimes 6281556Srgrimes switch (artyp) { 6291556Srgrimes case ISREG: 6301556Srgrimes if ((res > 0) && (res % BLKMULT)) { 6311556Srgrimes /* 6321556Srgrimes * try to fix up partial writes which are not BLKMULT 6331556Srgrimes * in size by forcing the runt record to next archive 6341556Srgrimes * volume 6351556Srgrimes */ 6361556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 6371556Srgrimes break; 6381556Srgrimes cpos -= (off_t)res; 6391556Srgrimes if (ftruncate(arfd, cpos) < 0) 6401556Srgrimes break; 6411556Srgrimes res = lstrval = 0; 6421556Srgrimes break; 6431556Srgrimes } 6441556Srgrimes if (res >= 0) 6451556Srgrimes break; 6461556Srgrimes /* 6471556Srgrimes * if file is out of space, handle it like a return of 0 6481556Srgrimes */ 6491556Srgrimes if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) 6501556Srgrimes res = lstrval = 0; 6511556Srgrimes break; 6521556Srgrimes case ISTAPE: 6531556Srgrimes case ISCHR: 6541556Srgrimes case ISBLK: 6551556Srgrimes if (res >= 0) 6561556Srgrimes break; 6571556Srgrimes if (errno == EACCES) { 65876017Skris paxwarn(0, "Write failed, archive is write protected."); 6591556Srgrimes res = lstrval = 0; 6601556Srgrimes return(0); 6611556Srgrimes } 6621556Srgrimes /* 6631556Srgrimes * see if we reached the end of media, if so force a change to 6641556Srgrimes * the next volume 6651556Srgrimes */ 6661556Srgrimes if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) 6671556Srgrimes res = lstrval = 0; 6681556Srgrimes break; 6691556Srgrimes case ISPIPE: 6701556Srgrimes default: 6711556Srgrimes /* 6721556Srgrimes * we cannot fix errors to these devices 6731556Srgrimes */ 6741556Srgrimes break; 6751556Srgrimes } 6761556Srgrimes 6771556Srgrimes /* 6781556Srgrimes * Better tell the user the bad news... 6791556Srgrimes * if this is a block aligned archive format, we may have a bad archive 68046684Skris * if the format wants the header to start at a BLKMULT boundary. While 6811556Srgrimes * we can deal with the mis-aligned data, it violates spec and other 6821556Srgrimes * archive readers will likely fail. if the format is not block 6831556Srgrimes * aligned, the user may be lucky (and the archive is ok). 6841556Srgrimes */ 6851556Srgrimes if (res >= 0) { 6861556Srgrimes if (res > 0) 6871556Srgrimes wr_trail = 1; 6881556Srgrimes io_ok = 1; 6891556Srgrimes } 6901556Srgrimes 6911556Srgrimes /* 6921556Srgrimes * If we were trying to rewrite the trailer and it didn't work, we 6931556Srgrimes * must quit right away. 6941556Srgrimes */ 6951556Srgrimes if (!wr_trail && (res <= 0)) { 69676017Skris paxwarn(1,"Unable to append, trailer re-write failed. Quitting."); 6971556Srgrimes return(res); 6981556Srgrimes } 6998855Srgrimes 7008855Srgrimes if (res == 0) 70176017Skris paxwarn(0, "End of archive volume %d reached", arvol); 7021556Srgrimes else if (res < 0) 70376017Skris syswarn(1, errno, "Failed write to archive volume: %d", arvol); 7041556Srgrimes else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0)) 70576017Skris paxwarn(0,"WARNING: partial archive write. Archive MAY BE FLAWED"); 7061556Srgrimes else 70776017Skris paxwarn(1,"WARNING: partial archive write. Archive IS FLAWED"); 7081556Srgrimes return(res); 7091556Srgrimes} 7101556Srgrimes 7111556Srgrimes/* 7121556Srgrimes * ar_rdsync() 7131556Srgrimes * Try to move past a bad spot on a flawed archive as needed to continue 7141556Srgrimes * I/O. Clears error flags to allow I/O to continue. 7151556Srgrimes * Return: 7161556Srgrimes * 0 when ok to try i/o again, -1 otherwise. 7171556Srgrimes */ 7181556Srgrimes 7191556Srgrimesint 7201556Srgrimesar_rdsync(void) 7211556Srgrimes{ 7221556Srgrimes long fsbz; 7231556Srgrimes off_t cpos; 7241556Srgrimes off_t mpos; 72576019Skris struct mtop mb; 7261556Srgrimes 7271556Srgrimes /* 7281556Srgrimes * Fail resync attempts at user request (done) or this is going to be 729108533Sschweikh * an update/append to an existing archive. If last i/o hit media end, 730108533Sschweikh * we need to go to the next volume not try a resync. 7311556Srgrimes */ 7321556Srgrimes if ((done > 0) || (lstrval == 0)) 7331556Srgrimes return(-1); 7341556Srgrimes 7351556Srgrimes if ((act == APPND) || (act == ARCHIVE)) { 73676017Skris paxwarn(1, "Cannot allow updates to an archive with flaws."); 7371556Srgrimes return(-1); 7381556Srgrimes } 7391556Srgrimes if (io_ok) 7401556Srgrimes did_io = 1; 7411556Srgrimes 7421556Srgrimes switch(artyp) { 7431556Srgrimes case ISTAPE: 7441556Srgrimes /* 7451556Srgrimes * if the last i/o was a successful data transfer, we assume 7461556Srgrimes * the fault is just a bad record on the tape that we are now 7471556Srgrimes * past. If we did not get any data since the last resync try 74846684Skris * to move the tape forward one PHYSICAL record past any 7491556Srgrimes * damaged tape section. Some tape drives are stubborn and need 7501556Srgrimes * to be pushed. 7511556Srgrimes */ 7521556Srgrimes if (io_ok) { 7531556Srgrimes io_ok = 0; 7541556Srgrimes lstrval = 1; 7551556Srgrimes break; 7561556Srgrimes } 7571556Srgrimes mb.mt_op = MTFSR; 7581556Srgrimes mb.mt_count = 1; 7591556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) 7601556Srgrimes break; 7611556Srgrimes lstrval = 1; 7621556Srgrimes break; 7631556Srgrimes case ISREG: 7641556Srgrimes case ISCHR: 7651556Srgrimes case ISBLK: 7661556Srgrimes /* 7671556Srgrimes * try to step over the bad part of the device. 7681556Srgrimes */ 7691556Srgrimes io_ok = 0; 7701556Srgrimes if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) 7711556Srgrimes fsbz = BLKMULT; 7721556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 7731556Srgrimes break; 7741556Srgrimes mpos = fsbz - (cpos % (off_t)fsbz); 7758855Srgrimes if (lseek(arfd, mpos, SEEK_CUR) < 0) 7761556Srgrimes break; 7771556Srgrimes lstrval = 1; 7781556Srgrimes break; 7791556Srgrimes case ISPIPE: 7801556Srgrimes default: 7811556Srgrimes /* 7821556Srgrimes * cannot recover on these archive device types 7831556Srgrimes */ 7841556Srgrimes io_ok = 0; 7851556Srgrimes break; 7861556Srgrimes } 7871556Srgrimes if (lstrval <= 0) { 78876017Skris paxwarn(1, "Unable to recover from an archive read failure."); 7891556Srgrimes return(-1); 7901556Srgrimes } 79176017Skris paxwarn(0, "Attempting to recover from an archive read failure."); 7921556Srgrimes return(0); 7931556Srgrimes} 7941556Srgrimes 7951556Srgrimes/* 7961556Srgrimes * ar_fow() 7971556Srgrimes * Move the I/O position within the archive foward the specified number of 7981556Srgrimes * bytes as supported by the device. If we cannot move the requested 7991556Srgrimes * number of bytes, return the actual number of bytes moved in skipped. 8001556Srgrimes * Return: 8011556Srgrimes * 0 if moved the requested distance, -1 on complete failure, 1 on 8021556Srgrimes * partial move (the amount moved is in skipped) 8031556Srgrimes */ 8041556Srgrimes 8051556Srgrimesint 8061556Srgrimesar_fow(off_t sksz, off_t *skipped) 8071556Srgrimes{ 8081556Srgrimes off_t cpos; 8091556Srgrimes off_t mpos; 8101556Srgrimes 8111556Srgrimes *skipped = 0; 8121556Srgrimes if (sksz <= 0) 8131556Srgrimes return(0); 8141556Srgrimes 8151556Srgrimes /* 8161556Srgrimes * we cannot move foward at EOF or error 8171556Srgrimes */ 8181556Srgrimes if (lstrval <= 0) 8191556Srgrimes return(lstrval); 8201556Srgrimes 8211556Srgrimes /* 8221556Srgrimes * Safer to read forward on devices where it is hard to find the end of 8231556Srgrimes * the media without reading to it. With tapes we cannot be sure of the 8241556Srgrimes * number of physical blocks to skip (we do not know physical block 8251556Srgrimes * size at this point), so we must only read foward on tapes! 8261556Srgrimes */ 8278855Srgrimes if (artyp != ISREG) 8281556Srgrimes return(0); 8291556Srgrimes 8301556Srgrimes /* 8311556Srgrimes * figure out where we are in the archive 8321556Srgrimes */ 8331556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) { 8348855Srgrimes /* 8351556Srgrimes * we can be asked to move farther than there are bytes in this 8361556Srgrimes * volume, if so, just go to file end and let normal buf_fill() 8371556Srgrimes * deal with the end of file (it will go to next volume by 8381556Srgrimes * itself) 8391556Srgrimes */ 8401556Srgrimes if ((mpos = cpos + sksz) > arsb.st_size) { 8411556Srgrimes *skipped = arsb.st_size - cpos; 8421556Srgrimes mpos = arsb.st_size; 8431556Srgrimes } else 8441556Srgrimes *skipped = sksz; 8451556Srgrimes if (lseek(arfd, mpos, SEEK_SET) >= 0) 8461556Srgrimes return(0); 8471556Srgrimes } 84876017Skris syswarn(1, errno, "Forward positioning operation on archive failed"); 8491556Srgrimes lstrval = -1; 8501556Srgrimes return(-1); 8511556Srgrimes} 8521556Srgrimes 8531556Srgrimes/* 8541556Srgrimes * ar_rev() 8551556Srgrimes * move the i/o position within the archive backwards the specified byte 8561556Srgrimes * count as supported by the device. With tapes drives we RESET rdblksz to 8571556Srgrimes * the PHYSICAL blocksize. 8581556Srgrimes * NOTE: We should only be called to move backwards so we can rewrite the 8591556Srgrimes * last records (the trailer) of an archive (APPEND). 8601556Srgrimes * Return: 8611556Srgrimes * 0 if moved the requested distance, -1 on complete failure 8621556Srgrimes */ 8631556Srgrimes 8641556Srgrimesint 8651556Srgrimesar_rev(off_t sksz) 8661556Srgrimes{ 8671556Srgrimes off_t cpos; 86876019Skris struct mtop mb; 86990113Simp int phyblk; 8701556Srgrimes 8711556Srgrimes /* 8721556Srgrimes * make sure we do not have try to reverse on a flawed archive 8731556Srgrimes */ 8741556Srgrimes if (lstrval < 0) 8751556Srgrimes return(lstrval); 8761556Srgrimes 8771556Srgrimes switch(artyp) { 8781556Srgrimes case ISPIPE: 8798855Srgrimes if (sksz <= 0) 8801556Srgrimes break; 8811556Srgrimes /* 8821556Srgrimes * cannot go backwards on these critters 8831556Srgrimes */ 88476017Skris paxwarn(1, "Reverse positioning on pipes is not supported."); 8851556Srgrimes lstrval = -1; 8861556Srgrimes return(-1); 8871556Srgrimes case ISREG: 8881556Srgrimes case ISBLK: 8891556Srgrimes case ISCHR: 8901556Srgrimes default: 8911556Srgrimes if (sksz <= 0) 8921556Srgrimes break; 8931556Srgrimes 8941556Srgrimes /* 8951556Srgrimes * For things other than files, backwards movement has a very 8961556Srgrimes * high probability of failure as we really do not know the 8971556Srgrimes * true attributes of the device we are talking to (the device 8981556Srgrimes * may not even have the ability to lseek() in any direction). 8991556Srgrimes * First we figure out where we are in the archive. 9001556Srgrimes */ 9011556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) { 90276017Skris syswarn(1, errno, 9031556Srgrimes "Unable to obtain current archive byte offset"); 9041556Srgrimes lstrval = -1; 9051556Srgrimes return(-1); 9061556Srgrimes } 9071556Srgrimes 9081556Srgrimes /* 9091556Srgrimes * we may try to go backwards past the start when the archive 9101556Srgrimes * is only a single record. If this hapens and we are on a 9111556Srgrimes * multi volume archive, we need to go to the end of the 9121556Srgrimes * previous volume and continue our movement backwards from 9131556Srgrimes * there. 9141556Srgrimes */ 9151556Srgrimes if ((cpos -= sksz) < (off_t)0L) { 9161556Srgrimes if (arvol > 1) { 9171556Srgrimes /* 9181556Srgrimes * this should never happen 9191556Srgrimes */ 92076017Skris paxwarn(1,"Reverse position on previous volume."); 9211556Srgrimes lstrval = -1; 9221556Srgrimes return(-1); 9231556Srgrimes } 9241556Srgrimes cpos = (off_t)0L; 9251556Srgrimes } 9261556Srgrimes if (lseek(arfd, cpos, SEEK_SET) < 0) { 92776017Skris syswarn(1, errno, "Unable to seek archive backwards"); 9281556Srgrimes lstrval = -1; 9291556Srgrimes return(-1); 9301556Srgrimes } 9311556Srgrimes break; 9321556Srgrimes case ISTAPE: 9331556Srgrimes /* 9341556Srgrimes * Calculate and move the proper number of PHYSICAL tape 9351556Srgrimes * blocks. If the sksz is not an even multiple of the physical 9361556Srgrimes * tape size, we cannot do the move (this should never happen). 9371556Srgrimes * (We also cannot handler trailers spread over two vols). 9381556Srgrimes * get_phys() also makes sure we are in front of the filemark. 9391556Srgrimes */ 9401556Srgrimes if ((phyblk = get_phys()) <= 0) { 9411556Srgrimes lstrval = -1; 9421556Srgrimes return(-1); 9431556Srgrimes } 9441556Srgrimes 9451556Srgrimes /* 9461556Srgrimes * make sure future tape reads only go by physical tape block 9471556Srgrimes * size (set rdblksz to the real size). 9481556Srgrimes */ 9491556Srgrimes rdblksz = phyblk; 9501556Srgrimes 9511556Srgrimes /* 9521556Srgrimes * if no movement is required, just return (we must be after 9531556Srgrimes * get_phys() so the physical blocksize is properly set) 9541556Srgrimes */ 9551556Srgrimes if (sksz <= 0) 9561556Srgrimes break; 9571556Srgrimes 9581556Srgrimes /* 9591556Srgrimes * ok we have to move. Make sure the tape drive can do it. 9601556Srgrimes */ 9611556Srgrimes if (sksz % phyblk) { 96276017Skris paxwarn(1, 9631556Srgrimes "Tape drive unable to backspace requested amount"); 9641556Srgrimes lstrval = -1; 9651556Srgrimes return(-1); 9661556Srgrimes } 9671556Srgrimes 9681556Srgrimes /* 9691556Srgrimes * move backwards the requested number of bytes 9701556Srgrimes */ 9711556Srgrimes mb.mt_op = MTBSR; 9721556Srgrimes mb.mt_count = sksz/phyblk; 9731556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 97476017Skris syswarn(1,errno, "Unable to backspace tape %d blocks.", 9751556Srgrimes mb.mt_count); 9761556Srgrimes lstrval = -1; 9771556Srgrimes return(-1); 9781556Srgrimes } 9791556Srgrimes break; 9801556Srgrimes } 9811556Srgrimes lstrval = 1; 9821556Srgrimes return(0); 9831556Srgrimes} 9841556Srgrimes 9851556Srgrimes/* 9861556Srgrimes * get_phys() 9871556Srgrimes * Determine the physical block size on a tape drive. We need the physical 9888855Srgrimes * block size so we know how many bytes we skip over when we move with 9891556Srgrimes * mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when 9901556Srgrimes * return. 9911556Srgrimes * This is one really SLOW routine... 9921556Srgrimes * Return: 9931556Srgrimes * physical block size if ok (ok > 0), -1 otherwise 9941556Srgrimes */ 9951556Srgrimes 9961556Srgrimesstatic int 9971556Srgrimesget_phys(void) 9981556Srgrimes{ 99990113Simp int padsz = 0; 100090113Simp int res; 100190113Simp int phyblk; 10021556Srgrimes struct mtop mb; 10031556Srgrimes char scbuf[MAXBLK]; 10041556Srgrimes 10051556Srgrimes /* 10061556Srgrimes * move to the file mark, and then back up one record and read it. 10071556Srgrimes * this should tell us the physical record size the tape is using. 10081556Srgrimes */ 10091556Srgrimes if (lstrval == 1) { 10101556Srgrimes /* 10111556Srgrimes * we know we are at file mark when we get back a 0 from 10121556Srgrimes * read() 10131556Srgrimes */ 10141556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10151556Srgrimes padsz += res; 10161556Srgrimes if (res < 0) { 101776017Skris syswarn(1, errno, "Unable to locate tape filemark."); 10181556Srgrimes return(-1); 10191556Srgrimes } 10201556Srgrimes } 10211556Srgrimes 10221556Srgrimes /* 10231556Srgrimes * move backwards over the file mark so we are at the end of the 10241556Srgrimes * last record. 10251556Srgrimes */ 10261556Srgrimes mb.mt_op = MTBSF; 10271556Srgrimes mb.mt_count = 1; 10281556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 102976017Skris syswarn(1, errno, "Unable to backspace over tape filemark."); 10301556Srgrimes return(-1); 10311556Srgrimes } 10321556Srgrimes 10331556Srgrimes /* 10341556Srgrimes * move backwards so we are in front of the last record and read it to 10351556Srgrimes * get physical tape blocksize. 10361556Srgrimes */ 10371556Srgrimes mb.mt_op = MTBSR; 10381556Srgrimes mb.mt_count = 1; 10391556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 104076017Skris syswarn(1, errno, "Unable to backspace over last tape block."); 10411556Srgrimes return(-1); 10421556Srgrimes } 10431556Srgrimes if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) { 104476017Skris syswarn(1, errno, "Cannot determine archive tape blocksize."); 10451556Srgrimes return(-1); 10461556Srgrimes } 10471556Srgrimes 10481556Srgrimes /* 10491556Srgrimes * read foward to the file mark, then back up in front of the filemark 10501556Srgrimes * (this is a bit paranoid, but should be safe to do). 10511556Srgrimes */ 10521556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10531556Srgrimes ; 10541556Srgrimes if (res < 0) { 105576017Skris syswarn(1, errno, "Unable to locate tape filemark."); 10561556Srgrimes return(-1); 10571556Srgrimes } 10581556Srgrimes mb.mt_op = MTBSF; 10591556Srgrimes mb.mt_count = 1; 10601556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 106176017Skris syswarn(1, errno, "Unable to backspace over tape filemark."); 10621556Srgrimes return(-1); 10631556Srgrimes } 10641556Srgrimes 10651556Srgrimes /* 10661556Srgrimes * set lstrval so we know that the filemark has not been seen 10671556Srgrimes */ 10681556Srgrimes lstrval = 1; 10691556Srgrimes 10701556Srgrimes /* 10711556Srgrimes * return if there was no padding 10721556Srgrimes */ 10731556Srgrimes if (padsz == 0) 10741556Srgrimes return(phyblk); 10751556Srgrimes 10761556Srgrimes /* 10771556Srgrimes * make sure we can move backwards over the padding. (this should 10781556Srgrimes * never fail). 10791556Srgrimes */ 10801556Srgrimes if (padsz % phyblk) { 108176017Skris paxwarn(1, "Tape drive unable to backspace requested amount"); 10821556Srgrimes return(-1); 10831556Srgrimes } 10841556Srgrimes 10851556Srgrimes /* 10861556Srgrimes * move backwards over the padding so the head is where it was when 10871556Srgrimes * we were first called (if required). 10881556Srgrimes */ 10891556Srgrimes mb.mt_op = MTBSR; 10901556Srgrimes mb.mt_count = padsz/phyblk; 10911556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 109276017Skris syswarn(1,errno,"Unable to backspace tape over %d pad blocks", 10931556Srgrimes mb.mt_count); 10941556Srgrimes return(-1); 10951556Srgrimes } 10961556Srgrimes return(phyblk); 10971556Srgrimes} 10981556Srgrimes 10991556Srgrimes/* 11001556Srgrimes * ar_next() 11011556Srgrimes * prompts the user for the next volume in this archive. For some devices 11021556Srgrimes * we may allow the media to be changed. Otherwise a new archive is 11031556Srgrimes * prompted for. By pax spec, if there is no controlling tty or an eof is 11041556Srgrimes * read on tty input, we must quit pax. 11051556Srgrimes * Return: 11061556Srgrimes * 0 when ready to continue, -1 when all done 11071556Srgrimes */ 11081556Srgrimes 11091556Srgrimesint 11101556Srgrimesar_next(void) 11111556Srgrimes{ 11121556Srgrimes char buf[PAXPATHLEN+2]; 11131556Srgrimes static int freeit = 0; 11141556Srgrimes sigset_t o_mask; 11151556Srgrimes 11161556Srgrimes /* 11171556Srgrimes * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so 11181556Srgrimes * things like writing EOF etc will be done) (Watch out ar_close() can 11191556Srgrimes * also be called via a signal handler, so we must prevent a race. 11201556Srgrimes */ 11211556Srgrimes if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0) 112276017Skris syswarn(0, errno, "Unable to set signal mask"); 11231556Srgrimes ar_close(); 112476017Skris if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0) 112576017Skris syswarn(0, errno, "Unable to restore signal mask"); 11261556Srgrimes 112776351Skris if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0) 11281556Srgrimes return(-1); 11291556Srgrimes 11301556Srgrimes tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0); 11311556Srgrimes 11321556Srgrimes /* 11331556Srgrimes * if i/o is on stdin or stdout, we cannot reopen it (we do not know 11341556Srgrimes * the name), the user will be forced to type it in. 11351556Srgrimes */ 1136114583Smarkm if (strcmp(arcname, stdo) && strcmp(arcname, stdn) && (artyp != ISREG) 11371556Srgrimes && (artyp != ISPIPE)) { 11381556Srgrimes if (artyp == ISTAPE) { 11391556Srgrimes tty_prnt("%s ready for archive tape volume: %d\n", 11401556Srgrimes arcname, arvol); 11411556Srgrimes tty_prnt("Load the NEXT TAPE on the tape drive"); 11421556Srgrimes } else { 11431556Srgrimes tty_prnt("%s ready for archive volume: %d\n", 11441556Srgrimes arcname, arvol); 11451556Srgrimes tty_prnt("Load the NEXT STORAGE MEDIA (if required)"); 11461556Srgrimes } 11471556Srgrimes 11481556Srgrimes if ((act == ARCHIVE) || (act == APPND)) 11491556Srgrimes tty_prnt(" and make sure it is WRITE ENABLED.\n"); 11501556Srgrimes else 11511556Srgrimes tty_prnt("\n"); 11521556Srgrimes 11531556Srgrimes for(;;) { 11541556Srgrimes tty_prnt("Type \"y\" to continue, \".\" to quit %s,", 11551556Srgrimes argv0); 11561556Srgrimes tty_prnt(" or \"s\" to switch to new device.\nIf you"); 11571556Srgrimes tty_prnt(" cannot change storage media, type \"s\"\n"); 11581556Srgrimes tty_prnt("Is the device ready and online? > "); 11591556Srgrimes 11601556Srgrimes if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){ 11611556Srgrimes done = 1; 11621556Srgrimes lstrval = -1; 11631556Srgrimes tty_prnt("Quitting %s!\n", argv0); 11641556Srgrimes vfpart = 0; 11651556Srgrimes return(-1); 11661556Srgrimes } 11671556Srgrimes 11681556Srgrimes if ((buf[0] == '\0') || (buf[1] != '\0')) { 11691556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 11701556Srgrimes continue; 11711556Srgrimes } 11721556Srgrimes 11731556Srgrimes switch (buf[0]) { 11741556Srgrimes case 'y': 11751556Srgrimes case 'Y': 11761556Srgrimes /* 11771556Srgrimes * we are to continue with the same device 11781556Srgrimes */ 11798855Srgrimes if (ar_open(arcname) >= 0) 11801556Srgrimes return(0); 11811556Srgrimes tty_prnt("Cannot re-open %s, try again\n", 11821556Srgrimes arcname); 11831556Srgrimes continue; 11841556Srgrimes case 's': 11851556Srgrimes case 'S': 11861556Srgrimes /* 11871556Srgrimes * user wants to open a different device 11881556Srgrimes */ 11891556Srgrimes tty_prnt("Switching to a different archive\n"); 11901556Srgrimes break; 11911556Srgrimes default: 11921556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 11931556Srgrimes continue; 11941556Srgrimes } 11951556Srgrimes break; 11961556Srgrimes } 11971556Srgrimes } else 11981556Srgrimes tty_prnt("Ready for archive volume: %d\n", arvol); 11991556Srgrimes 12001556Srgrimes /* 12011556Srgrimes * have to go to a different archive 12021556Srgrimes */ 12031556Srgrimes for (;;) { 12041556Srgrimes tty_prnt("Input archive name or \".\" to quit %s.\n", argv0); 12051556Srgrimes tty_prnt("Archive name > "); 12061556Srgrimes 12071556Srgrimes if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) { 12081556Srgrimes done = 1; 12091556Srgrimes lstrval = -1; 12101556Srgrimes tty_prnt("Quitting %s!\n", argv0); 12111556Srgrimes vfpart = 0; 12121556Srgrimes return(-1); 12131556Srgrimes } 12141556Srgrimes if (buf[0] == '\0') { 12151556Srgrimes tty_prnt("Empty file name, try again\n"); 12161556Srgrimes continue; 12171556Srgrimes } 121876019Skris if (!strcmp(buf, "..")) { 121976019Skris tty_prnt("Illegal file name: .. try again\n"); 122076019Skris continue; 122176019Skris } 12221556Srgrimes if (strlen(buf) > PAXPATHLEN) { 12231556Srgrimes tty_prnt("File name too long, try again\n"); 12241556Srgrimes continue; 12251556Srgrimes } 12261556Srgrimes 12271556Srgrimes /* 12281556Srgrimes * try to open new archive 12291556Srgrimes */ 12301556Srgrimes if (ar_open(buf) >= 0) { 12311556Srgrimes if (freeit) { 1232114583Smarkm (void)free((char *)(uintptr_t)arcname); 12331556Srgrimes freeit = 0; 12341556Srgrimes } 12351556Srgrimes if ((arcname = strdup(buf)) == NULL) { 12361556Srgrimes done = 1; 12371556Srgrimes lstrval = -1; 123876017Skris paxwarn(0, "Cannot save archive name."); 12391556Srgrimes return(-1); 12401556Srgrimes } 12411556Srgrimes freeit = 1; 12421556Srgrimes break; 12431556Srgrimes } 12441556Srgrimes tty_prnt("Cannot open %s, try again\n", buf); 12451556Srgrimes continue; 12461556Srgrimes } 12471556Srgrimes return(0); 12481556Srgrimes} 124976286Skris 125076286Skris/* 125176286Skris * ar_start_gzip() 125276286Skris * starts the gzip compression/decompression process as a child, using magic 125376286Skris * to keep the fd the same in the calling function (parent). 125476286Skris */ 125576286Skrisvoid 1256114583Smarkmar_start_gzip(int fd, const char *gzip_prog, int wr) 125776286Skris{ 125876286Skris int fds[2]; 1259114583Smarkm const char *gzip_flags; 126076286Skris 126176286Skris if (pipe(fds) < 0) 126276286Skris err(1, "could not pipe"); 126376286Skris zpid = fork(); 126476286Skris if (zpid < 0) 126576286Skris err(1, "could not fork"); 126676286Skris 126776286Skris /* parent */ 126876286Skris if (zpid) { 126976286Skris if (wr) 127076286Skris dup2(fds[1], fd); 127176286Skris else 127276286Skris dup2(fds[0], fd); 127376286Skris close(fds[0]); 127476286Skris close(fds[1]); 127576286Skris } else { 127676286Skris if (wr) { 127776286Skris dup2(fds[0], STDIN_FILENO); 127876286Skris dup2(fd, STDOUT_FILENO); 127976286Skris gzip_flags = "-c"; 128076286Skris } else { 128176286Skris dup2(fds[1], STDOUT_FILENO); 128276286Skris dup2(fd, STDIN_FILENO); 128376286Skris gzip_flags = "-dc"; 128476286Skris } 128576286Skris close(fds[0]); 128676286Skris close(fds[1]); 1287114583Smarkm if (execlp(gzip_prog, gzip_prog, gzip_flags, 128879452Sbrian (char *)NULL) < 0) 128976286Skris err(1, "could not exec"); 129076286Skris /* NOTREACHED */ 129176286Skris } 129276286Skris} 1293