ar_io.c revision 8855
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. 363044Sdg * 378855Srgrimes * $Id: ar_io.c,v 1.2 1994/09/24 02:56:11 davidg Exp $ 381556Srgrimes */ 391556Srgrimes 401556Srgrimes#ifndef lint 411556Srgrimesstatic char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; 421556Srgrimes#endif /* not lint */ 431556Srgrimes 441556Srgrimes#include <sys/types.h> 451556Srgrimes#include <sys/time.h> 461556Srgrimes#include <sys/stat.h> 471556Srgrimes#include <sys/ioctl.h> 481556Srgrimes#include <sys/mtio.h> 491556Srgrimes#include <sys/param.h> 501556Srgrimes#include <signal.h> 511556Srgrimes#include <string.h> 521556Srgrimes#include <fcntl.h> 531556Srgrimes#include <unistd.h> 541556Srgrimes#include <stdio.h> 551556Srgrimes#include <ctype.h> 561556Srgrimes#include <errno.h> 571556Srgrimes#include <stdlib.h> 581556Srgrimes#include "pax.h" 591556Srgrimes#include "extern.h" 601556Srgrimes 611556Srgrimes/* 621556Srgrimes * Routines which deal directly with the archive I/O device/file. 631556Srgrimes */ 641556Srgrimes 651556Srgrimes#define DMOD 0666 /* default mode of created archives */ 661556Srgrimes#define EXT_MODE O_RDONLY /* open mode for list/extract */ 671556Srgrimes#define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */ 681556Srgrimes#define APP_MODE O_RDWR /* mode for append */ 691556Srgrimes#define STDO "<STDOUT>" /* psuedo name for stdout */ 701556Srgrimes#define STDN "<STDIN>" /* psuedo name for stdin */ 711556Srgrimesstatic int arfd = -1; /* archive file descriptor */ 721556Srgrimesstatic int artyp = ISREG; /* archive type: file/FIFO/tape */ 731556Srgrimesstatic int arvol = 1; /* archive volume number */ 741556Srgrimesstatic int lstrval = -1; /* return value from last i/o */ 751556Srgrimesstatic int io_ok; /* i/o worked on volume after resync */ 761556Srgrimesstatic int did_io; /* did i/o ever occur on volume? */ 771556Srgrimesstatic int done; /* set via tty termination */ 781556Srgrimesstatic struct stat arsb; /* stat of archive device at open */ 791556Srgrimesstatic int invld_rec; /* tape has out of spec record size */ 801556Srgrimesstatic int wr_trail = 1; /* trailer was rewritten in append */ 811556Srgrimesstatic int can_unlnk = 0; /* do we unlink null archives? */ 821556Srgrimeschar *arcname; /* printable name of archive */ 831556Srgrimes 841556Srgrimesstatic int get_phys __P((void)); 851556Srgrimesextern sigset_t s_mask; 861556Srgrimes 871556Srgrimes/* 881556Srgrimes * ar_open() 891556Srgrimes * Opens the next archive volume. Determines the type of the device and 901556Srgrimes * sets up block sizes as required by the archive device and the format. 911556Srgrimes * Note: we may be called with name == NULL on the first open only. 921556Srgrimes * Return: 931556Srgrimes * -1 on failure, 0 otherwise 941556Srgrimes */ 951556Srgrimes 961556Srgrimes#if __STDC__ 971556Srgrimesint 981556Srgrimesar_open(char *name) 991556Srgrimes#else 1001556Srgrimesint 1011556Srgrimesar_open(name) 1021556Srgrimes char *name; 1031556Srgrimes#endif 1041556Srgrimes{ 1051556Srgrimes struct mtget mb; 1061556Srgrimes 1071556Srgrimes if (arfd != -1) 1081556Srgrimes (void)close(arfd); 1091556Srgrimes arfd = -1; 1101556Srgrimes can_unlnk = did_io = io_ok = invld_rec = 0; 1111556Srgrimes artyp = ISREG; 1121556Srgrimes flcnt = 0; 1131556Srgrimes 1141556Srgrimes /* 1151556Srgrimes * open based on overall operation mode 1161556Srgrimes */ 1171556Srgrimes switch (act) { 1181556Srgrimes case LIST: 1191556Srgrimes case EXTRACT: 1201556Srgrimes if (name == NULL) { 1211556Srgrimes arfd = STDIN_FILENO; 1221556Srgrimes arcname = STDN; 1231556Srgrimes } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) 1241556Srgrimes syswarn(0, errno, "Failed open to read on %s", name); 1251556Srgrimes break; 1261556Srgrimes case ARCHIVE: 1271556Srgrimes if (name == NULL) { 1281556Srgrimes arfd = STDOUT_FILENO; 1291556Srgrimes arcname = STDO; 1301556Srgrimes } else if ((arfd = open(name, AR_MODE, DMOD)) < 0) 1311556Srgrimes syswarn(0, errno, "Failed open to write on %s", name); 1321556Srgrimes else 1331556Srgrimes can_unlnk = 1; 1341556Srgrimes break; 1351556Srgrimes case APPND: 1361556Srgrimes if (name == NULL) { 1371556Srgrimes arfd = STDOUT_FILENO; 1381556Srgrimes arcname = STDO; 1391556Srgrimes } else if ((arfd = open(name, APP_MODE, DMOD)) < 0) 1401556Srgrimes syswarn(0, errno, "Failed open to read/write on %s", 1411556Srgrimes name); 1421556Srgrimes break; 1431556Srgrimes case COPY: 1441556Srgrimes /* 1451556Srgrimes * arfd not used in COPY mode 1461556Srgrimes */ 1471556Srgrimes arcname = "<NONE>"; 1481556Srgrimes lstrval = 1; 1491556Srgrimes return(0); 1501556Srgrimes } 1511556Srgrimes if (arfd < 0) 1521556Srgrimes return(-1); 1531556Srgrimes 1541556Srgrimes /* 1551556Srgrimes * set up is based on device type 1561556Srgrimes */ 1571556Srgrimes if (fstat(arfd, &arsb) < 0) { 1581556Srgrimes syswarn(0, errno, "Failed stat on %s", arcname); 1591556Srgrimes (void)close(arfd); 1601556Srgrimes arfd = -1; 1611556Srgrimes can_unlnk = 0; 1621556Srgrimes return(-1); 1631556Srgrimes } 1641556Srgrimes if (S_ISDIR(arsb.st_mode)) { 1651556Srgrimes warn(0, "Cannot write an archive on top of a directory %s", 1661556Srgrimes arcname); 1671556Srgrimes (void)close(arfd); 1681556Srgrimes arfd = -1; 1691556Srgrimes can_unlnk = 0; 1701556Srgrimes return(-1); 1711556Srgrimes } 1721556Srgrimes 1731556Srgrimes if (S_ISCHR(arsb.st_mode)) 1741556Srgrimes artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; 1751556Srgrimes else if (S_ISBLK(arsb.st_mode)) 1761556Srgrimes artyp = ISBLK; 1771556Srgrimes else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) 1781556Srgrimes artyp = ISPIPE; 1791556Srgrimes else 1801556Srgrimes artyp = ISREG; 1811556Srgrimes 1821556Srgrimes /* 1831556Srgrimes * make sure we beyond any doubt that we only can unlink regular files 1841556Srgrimes * we created 1851556Srgrimes */ 1861556Srgrimes if (artyp != ISREG) 1871556Srgrimes can_unlnk = 0; 1881556Srgrimes /* 1891556Srgrimes * if we are writing, we are done 1901556Srgrimes */ 1911556Srgrimes if (act == ARCHIVE) { 1921556Srgrimes blksz = rdblksz = wrblksz; 1931556Srgrimes lstrval = 1; 1941556Srgrimes return(0); 1951556Srgrimes } 1961556Srgrimes 1971556Srgrimes /* 1981556Srgrimes * set default blksz on read. APPNDs writes rdblksz on the last volume 1991556Srgrimes * On all new archive volumes, we shift to wrblksz (if the user 2001556Srgrimes * specified one, otherwize we will continue to use rdblksz). We 2011556Srgrimes * must to set blocksize based on what kind of device the archive is 2021556Srgrimes * stored. 2031556Srgrimes */ 2041556Srgrimes switch(artyp) { 2051556Srgrimes case ISTAPE: 2061556Srgrimes /* 2071556Srgrimes * Tape drives come in at least two flavors. Those that support 2081556Srgrimes * variable sized records and those that have fixed sized 2091556Srgrimes * records. They must be treated differently. For tape drives 2101556Srgrimes * that support variable sized records, we must make large 2111556Srgrimes * reads to make sure we get the entire record, otherwise we 2121556Srgrimes * will just get the first part of the record (up to size we 2131556Srgrimes * asked). Tapes with fixed sized records may or may not return 2141556Srgrimes * multiple records in a single read. We really do not care 2151556Srgrimes * what the physical record size is UNLESS we are going to 2161556Srgrimes * append. (We will need the physical block size to rewrite 2171556Srgrimes * the trailer). Only when we are appending do we go to the 2181556Srgrimes * effort to figure out the true PHYSICAL record size. 2191556Srgrimes */ 2201556Srgrimes blksz = rdblksz = MAXBLK; 2211556Srgrimes break; 2221556Srgrimes case ISPIPE: 2231556Srgrimes case ISBLK: 2241556Srgrimes case ISCHR: 2251556Srgrimes /* 2261556Srgrimes * Blocksize is not a major issue with these devices (but must 2271556Srgrimes * be kept a multiple of 512). If the user specified a write 2281556Srgrimes * block size, we use that to read. Under append, we must 2291556Srgrimes * always keep blksz == rdblksz. Otherwise we go ahead and use 2301556Srgrimes * the device optimal blocksize as (and if) returned by stat 2311556Srgrimes * and if it is within pax specs. 2321556Srgrimes */ 2331556Srgrimes if ((act == APPND) && wrblksz) { 2341556Srgrimes blksz = rdblksz = wrblksz; 2351556Srgrimes break; 2361556Srgrimes } 2371556Srgrimes 2381556Srgrimes if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && 2391556Srgrimes ((arsb.st_blksize % BLKMULT) == 0)) 2401556Srgrimes rdblksz = arsb.st_blksize; 2411556Srgrimes else 2421556Srgrimes rdblksz = DEVBLK; 2431556Srgrimes /* 2441556Srgrimes * For performance go for large reads when we can without harm 2451556Srgrimes */ 2461556Srgrimes if ((act == APPND) || (artyp == ISCHR)) 2471556Srgrimes blksz = rdblksz; 2481556Srgrimes else 2491556Srgrimes blksz = MAXBLK; 2501556Srgrimes break; 2511556Srgrimes case ISREG: 2521556Srgrimes /* 2531556Srgrimes * if the user specified wrblksz works, use it. Under appends 2541556Srgrimes * we must always keep blksz == rdblksz 2551556Srgrimes */ 2561556Srgrimes if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ 2571556Srgrimes blksz = rdblksz = wrblksz; 2581556Srgrimes break; 2591556Srgrimes } 2601556Srgrimes /* 2611556Srgrimes * See if we can find the blocking factor from the file size 2621556Srgrimes */ 2631556Srgrimes for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) 2641556Srgrimes if ((arsb.st_size % rdblksz) == 0) 2651556Srgrimes break; 2661556Srgrimes /* 2671556Srgrimes * When we cannont find a match, we may have a flawed archive. 2681556Srgrimes */ 2691556Srgrimes if (rdblksz <= 0) 2701556Srgrimes rdblksz = FILEBLK; 2711556Srgrimes /* 2721556Srgrimes * for performance go for large reads when we can 2731556Srgrimes */ 2741556Srgrimes if (act == APPND) 2751556Srgrimes blksz = rdblksz; 2761556Srgrimes else 2771556Srgrimes blksz = MAXBLK; 2781556Srgrimes break; 2791556Srgrimes default: 2801556Srgrimes /* 2818855Srgrimes * should never happen, worse case, slow... 2821556Srgrimes */ 2831556Srgrimes blksz = rdblksz = BLKMULT; 2841556Srgrimes break; 2851556Srgrimes } 2861556Srgrimes lstrval = 1; 2871556Srgrimes return(0); 2881556Srgrimes} 2891556Srgrimes 2901556Srgrimes/* 2911556Srgrimes * ar_close() 2921556Srgrimes * closes archive device, increments volume number, and prints i/o summary 2931556Srgrimes */ 2941556Srgrimes#if __STDC__ 2951556Srgrimesvoid 2961556Srgrimesar_close(void) 2971556Srgrimes#else 2981556Srgrimesvoid 2991556Srgrimesar_close() 3001556Srgrimes#endif 3011556Srgrimes{ 3021556Srgrimes FILE *outf; 3031556Srgrimes 3041556Srgrimes if (arfd < 0) { 3051556Srgrimes did_io = io_ok = flcnt = 0; 3061556Srgrimes return; 3071556Srgrimes } 3081556Srgrimes 3091556Srgrimes if (act == LIST) 3101556Srgrimes outf = stdout; 3111556Srgrimes else 3121556Srgrimes outf = stderr; 3131556Srgrimes 3141556Srgrimes /* 3151556Srgrimes * Close archive file. This may take a LONG while on tapes (we may be 3161556Srgrimes * forced to wait for the rewind to complete) so tell the user what is 3171556Srgrimes * going on (this avoids the user hitting control-c thinking pax is 3181556Srgrimes * broken). 3191556Srgrimes */ 3201556Srgrimes if (vflag && (artyp == ISTAPE)) { 3211556Srgrimes if (vfpart) 3221556Srgrimes (void)putc('\n', outf); 3231556Srgrimes (void)fprintf(outf, 3241556Srgrimes "%s: Waiting for tape drive close to complete...", 3251556Srgrimes argv0); 3261556Srgrimes (void)fflush(outf); 3271556Srgrimes } 3281556Srgrimes 3291556Srgrimes /* 3301556Srgrimes * if nothing was written to the archive (and we created it), we remove 3311556Srgrimes * it 3321556Srgrimes */ 3331556Srgrimes if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && 3341556Srgrimes (arsb.st_size == 0)) { 3351556Srgrimes (void)unlink(arcname); 3361556Srgrimes can_unlnk = 0; 3371556Srgrimes } 3381556Srgrimes 3391556Srgrimes (void)close(arfd); 3401556Srgrimes 3411556Srgrimes if (vflag && (artyp == ISTAPE)) { 3421556Srgrimes (void)fputs("done.\n", outf); 3431556Srgrimes vfpart = 0; 3441556Srgrimes (void)fflush(outf); 3451556Srgrimes } 3461556Srgrimes arfd = -1; 3471556Srgrimes 3481556Srgrimes if (!io_ok && !did_io) { 3491556Srgrimes flcnt = 0; 3501556Srgrimes return; 3511556Srgrimes } 3521556Srgrimes did_io = io_ok = 0; 3531556Srgrimes 3541556Srgrimes /* 3551556Srgrimes * The volume number is only increased when the last device has data 3561556Srgrimes * and we have already determined the archive format. 3571556Srgrimes */ 3581556Srgrimes if (frmt != NULL) 3591556Srgrimes ++arvol; 3601556Srgrimes 3611556Srgrimes if (!vflag) { 3621556Srgrimes flcnt = 0; 3631556Srgrimes return; 3641556Srgrimes } 3651556Srgrimes 3661556Srgrimes /* 3671556Srgrimes * Print out a summary of I/O for this archive volume. 3681556Srgrimes */ 3691556Srgrimes if (vfpart) { 3701556Srgrimes (void)putc('\n', outf); 3711556Srgrimes vfpart = 0; 3721556Srgrimes } 3731556Srgrimes 3741556Srgrimes /* 3751556Srgrimes * If we have not determined the format yet, we just say how many bytes 3761556Srgrimes * we have skipped over looking for a header to id. there is no way we 3771556Srgrimes * could have written anything yet. 3781556Srgrimes */ 3791556Srgrimes if (frmt == NULL) { 3801556Srgrimes# ifdef NET2_STAT 3811556Srgrimes (void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n", 3821556Srgrimes# else 3831556Srgrimes (void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n", 3841556Srgrimes# endif 3851556Srgrimes argv0, rdcnt); 3861556Srgrimes (void)fflush(outf); 3871556Srgrimes flcnt = 0; 3881556Srgrimes return; 3891556Srgrimes } 3901556Srgrimes 3911556Srgrimes (void)fprintf(outf, 3921556Srgrimes# ifdef NET2_STAT 3931556Srgrimes "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n", 3941556Srgrimes# else 3951556Srgrimes "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n", 3961556Srgrimes# endif 3971556Srgrimes argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt); 3981556Srgrimes (void)fflush(outf); 3991556Srgrimes flcnt = 0; 4001556Srgrimes} 4011556Srgrimes 4021556Srgrimes/* 4031556Srgrimes * ar_drain() 4041556Srgrimes * drain any archive format independent padding from an archive read 4051556Srgrimes * from a socket or a pipe. This is to prevent the process on the 4061556Srgrimes * other side of the pipe from getting a SIGPIPE (pax will stop 4071556Srgrimes * reading an archive once a format dependent trailer is detected). 4081556Srgrimes */ 4091556Srgrimes#if __STDC__ 4101556Srgrimesvoid 4111556Srgrimesar_drain(void) 4121556Srgrimes#else 4131556Srgrimesvoid 4141556Srgrimesar_drain() 4151556Srgrimes#endif 4161556Srgrimes{ 4171556Srgrimes register int res; 4181556Srgrimes char drbuf[MAXBLK]; 4191556Srgrimes 4201556Srgrimes /* 4211556Srgrimes * we only drain from a pipe/socket. Other devices can be closed 4221556Srgrimes * without reading up to end of file. We sure hope that pipe is closed 4231556Srgrimes * on the other side so we will get an EOF. 4241556Srgrimes */ 4251556Srgrimes if ((artyp != ISPIPE) || (lstrval <= 0)) 4261556Srgrimes return; 4271556Srgrimes 4281556Srgrimes /* 4291556Srgrimes * keep reading until pipe is drained 4301556Srgrimes */ 4311556Srgrimes while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) 4321556Srgrimes ; 4331556Srgrimes lstrval = res; 4341556Srgrimes} 4351556Srgrimes 4361556Srgrimes/* 4371556Srgrimes * ar_set_wr() 4381556Srgrimes * Set up device right before switching from read to write in an append. 4391556Srgrimes * device dependent code (if required) to do this should be added here. 4401556Srgrimes * For all archive devices we are already positioned at the place we want 4411556Srgrimes * to start writing when this routine is called. 4421556Srgrimes * Return: 4431556Srgrimes * 0 if all ready to write, -1 otherwise 4441556Srgrimes */ 4451556Srgrimes 4461556Srgrimes#if __STDC__ 4471556Srgrimesint 4481556Srgrimesar_set_wr(void) 4491556Srgrimes#else 4501556Srgrimesint 4511556Srgrimesar_set_wr() 4521556Srgrimes#endif 4531556Srgrimes{ 4541556Srgrimes off_t cpos; 4551556Srgrimes 4561556Srgrimes /* 4571556Srgrimes * we must make sure the trailer is rewritten on append, ar_next() 4581556Srgrimes * will stop us if the archive containing the trailer was not written 4591556Srgrimes */ 4601556Srgrimes wr_trail = 0; 4618855Srgrimes 4628855Srgrimes /* 4631556Srgrimes * Add any device dependent code as required here 4641556Srgrimes */ 4651556Srgrimes if (artyp != ISREG) 4661556Srgrimes return(0); 4671556Srgrimes /* 4681556Srgrimes * Ok we have an archive in a regular file. If we were rewriting a 4691556Srgrimes * file, we must get rid of all the stuff after the current offset 4701556Srgrimes * (it was not written by pax). 4711556Srgrimes */ 4721556Srgrimes if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) || 4731556Srgrimes (ftruncate(arfd, cpos) < 0)) { 4741556Srgrimes syswarn(1, errno, "Unable to truncate archive file"); 4751556Srgrimes return(-1); 4761556Srgrimes } 4771556Srgrimes return(0); 4781556Srgrimes} 4791556Srgrimes 4801556Srgrimes/* 4811556Srgrimes * ar_app_ok() 4821556Srgrimes * check if the last volume in the archive allows appends. We cannot check 4838855Srgrimes * this until we are ready to write since there is no spec that says all 4841556Srgrimes * volumes in a single archive have to be of the same type... 4851556Srgrimes * Return: 4861556Srgrimes * 0 if we can append, -1 otherwise. 4871556Srgrimes */ 4881556Srgrimes 4891556Srgrimes#if __STDC__ 4901556Srgrimesint 4911556Srgrimesar_app_ok(void) 4921556Srgrimes#else 4931556Srgrimesint 4941556Srgrimesar_app_ok() 4951556Srgrimes#endif 4961556Srgrimes{ 4971556Srgrimes if (artyp == ISPIPE) { 4981556Srgrimes warn(1, "Cannot append to an archive obtained from a pipe."); 4991556Srgrimes return(-1); 5001556Srgrimes } 5011556Srgrimes 5021556Srgrimes if (!invld_rec) 5031556Srgrimes return(0); 5041556Srgrimes warn(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 5181556Srgrimes#if __STDC__ 5191556Srgrimesint 5201556Srgrimesar_read(register char *buf, register int cnt) 5211556Srgrimes#else 5221556Srgrimesint 5231556Srgrimesar_read(buf, cnt) 5241556Srgrimes register char *buf; 5251556Srgrimes register int cnt; 5261556Srgrimes#endif 5271556Srgrimes{ 5281556Srgrimes register int res = 0; 5291556Srgrimes 5301556Srgrimes /* 5311556Srgrimes * if last i/o was in error, no more reads until reset or new volume 5321556Srgrimes */ 5331556Srgrimes if (lstrval <= 0) 5341556Srgrimes return(lstrval); 5351556Srgrimes 5361556Srgrimes /* 5371556Srgrimes * how we read must be based on device type 5381556Srgrimes */ 5391556Srgrimes switch (artyp) { 5401556Srgrimes case ISTAPE: 5411556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5421556Srgrimes /* 5431556Srgrimes * CAUTION: tape systems may not always return the same 5441556Srgrimes * sized records so we leave blksz == MAXBLK. The 5451556Srgrimes * physical record size that a tape drive supports is 5461556Srgrimes * very hard to determine in a uniform and portable 5471556Srgrimes * manner. 5481556Srgrimes */ 5491556Srgrimes io_ok = 1; 5501556Srgrimes if (res != rdblksz) { 5511556Srgrimes /* 5521556Srgrimes * Record size changed. If this is happens on 5531556Srgrimes * any record after the first, we probably have 5541556Srgrimes * a tape drive which has a fixed record size 5551556Srgrimes * we are getting multiple records in a single 5561556Srgrimes * read). Watch out for record blocking that 5571556Srgrimes * violates pax spec (must be a multiple of 5581556Srgrimes * BLKMULT). 5591556Srgrimes */ 5601556Srgrimes rdblksz = res; 5611556Srgrimes if (rdblksz % BLKMULT) 5621556Srgrimes invld_rec = 1; 5631556Srgrimes } 5641556Srgrimes return(res); 5651556Srgrimes } 5661556Srgrimes break; 5671556Srgrimes case ISREG: 5681556Srgrimes case ISBLK: 5691556Srgrimes case ISCHR: 5701556Srgrimes case ISPIPE: 5711556Srgrimes default: 5721556Srgrimes /* 5731556Srgrimes * Files are so easy to deal with. These other things cannot 5741556Srgrimes * be trusted at all. So when we are dealing with character 5751556Srgrimes * devices and pipes we just take what they have ready for us 5761556Srgrimes * and return. Trying to do anything else with them runs the 5771556Srgrimes * risk of failure. 5781556Srgrimes */ 5791556Srgrimes if ((res = read(arfd, buf, cnt)) > 0) { 5801556Srgrimes io_ok = 1; 5811556Srgrimes return(res); 5821556Srgrimes } 5831556Srgrimes break; 5841556Srgrimes } 5851556Srgrimes 5861556Srgrimes /* 5871556Srgrimes * We are in trouble at this point, something is broken... 5881556Srgrimes */ 5891556Srgrimes lstrval = res; 5901556Srgrimes if (res < 0) 5911556Srgrimes syswarn(1, errno, "Failed read on archive volume %d", arvol); 5921556Srgrimes else 5931556Srgrimes warn(0, "End of archive volume %d reached", arvol); 5941556Srgrimes return(res); 5958855Srgrimes} 5961556Srgrimes 5971556Srgrimes/* 5981556Srgrimes * ar_write() 5991556Srgrimes * Write a specified number of bytes in supplied buffer to the archive 6001556Srgrimes * device so it appears as a single "block". Deals with errors and tries 6011556Srgrimes * to recover when faced with short writes. 6021556Srgrimes * Return: 6031556Srgrimes * Number of bytes written. 0 indicates end of volume reached and with no 6041556Srgrimes * flaws (as best that can be detected). A -1 indicates an unrecoverable 6051556Srgrimes * error in the archive occured. 6061556Srgrimes */ 6071556Srgrimes 6081556Srgrimes#if __STDC__ 6091556Srgrimesint 6101556Srgrimesar_write(register char *buf, register int bsz) 6111556Srgrimes#else 6121556Srgrimesint 6131556Srgrimesar_write(buf, bsz) 6141556Srgrimes register char *buf; 6151556Srgrimes register int bsz; 6161556Srgrimes#endif 6171556Srgrimes{ 6181556Srgrimes register int res; 6191556Srgrimes off_t cpos; 6201556Srgrimes 6211556Srgrimes /* 6221556Srgrimes * do not allow pax to create a "bad" archive. Once a write fails on 6231556Srgrimes * an archive volume prevent further writes to it. 6241556Srgrimes */ 6251556Srgrimes if (lstrval <= 0) 6261556Srgrimes return(lstrval); 6271556Srgrimes 6281556Srgrimes if ((res = write(arfd, buf, bsz)) == bsz) { 6291556Srgrimes wr_trail = 1; 6301556Srgrimes io_ok = 1; 6311556Srgrimes return(bsz); 6321556Srgrimes } 6331556Srgrimes /* 6341556Srgrimes * write broke, see what we can do with it. We try to send any partial 6351556Srgrimes * writes that may violate pax spec to the next archive volume. 6361556Srgrimes */ 6371556Srgrimes if (res < 0) 6381556Srgrimes lstrval = res; 6391556Srgrimes else 6401556Srgrimes lstrval = 0; 6411556Srgrimes 6421556Srgrimes switch (artyp) { 6431556Srgrimes case ISREG: 6441556Srgrimes if ((res > 0) && (res % BLKMULT)) { 6451556Srgrimes /* 6461556Srgrimes * try to fix up partial writes which are not BLKMULT 6471556Srgrimes * in size by forcing the runt record to next archive 6481556Srgrimes * volume 6491556Srgrimes */ 6501556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 6511556Srgrimes break; 6521556Srgrimes cpos -= (off_t)res; 6531556Srgrimes if (ftruncate(arfd, cpos) < 0) 6541556Srgrimes break; 6551556Srgrimes res = lstrval = 0; 6561556Srgrimes break; 6571556Srgrimes } 6581556Srgrimes if (res >= 0) 6591556Srgrimes break; 6601556Srgrimes /* 6611556Srgrimes * if file is out of space, handle it like a return of 0 6621556Srgrimes */ 6631556Srgrimes if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) 6641556Srgrimes res = lstrval = 0; 6651556Srgrimes break; 6661556Srgrimes case ISTAPE: 6671556Srgrimes case ISCHR: 6681556Srgrimes case ISBLK: 6691556Srgrimes if (res >= 0) 6701556Srgrimes break; 6711556Srgrimes if (errno == EACCES) { 6721556Srgrimes warn(0, "Write failed, archive is write protected."); 6731556Srgrimes res = lstrval = 0; 6741556Srgrimes return(0); 6751556Srgrimes } 6761556Srgrimes /* 6771556Srgrimes * see if we reached the end of media, if so force a change to 6781556Srgrimes * the next volume 6791556Srgrimes */ 6801556Srgrimes if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) 6811556Srgrimes res = lstrval = 0; 6821556Srgrimes break; 6831556Srgrimes case ISPIPE: 6841556Srgrimes default: 6851556Srgrimes /* 6861556Srgrimes * we cannot fix errors to these devices 6871556Srgrimes */ 6881556Srgrimes break; 6891556Srgrimes } 6901556Srgrimes 6911556Srgrimes /* 6921556Srgrimes * Better tell the user the bad news... 6931556Srgrimes * if this is a block aligned archive format, we may have a bad archive 6941556Srgrimes * if the format wants the header to start at a BLKMULT boundry. While 6951556Srgrimes * we can deal with the mis-aligned data, it violates spec and other 6961556Srgrimes * archive readers will likely fail. if the format is not block 6971556Srgrimes * aligned, the user may be lucky (and the archive is ok). 6981556Srgrimes */ 6991556Srgrimes if (res >= 0) { 7001556Srgrimes if (res > 0) 7011556Srgrimes wr_trail = 1; 7021556Srgrimes io_ok = 1; 7031556Srgrimes } 7041556Srgrimes 7051556Srgrimes /* 7061556Srgrimes * If we were trying to rewrite the trailer and it didn't work, we 7071556Srgrimes * must quit right away. 7081556Srgrimes */ 7091556Srgrimes if (!wr_trail && (res <= 0)) { 7101556Srgrimes warn(1,"Unable to append, trailer re-write failed. Quitting."); 7111556Srgrimes return(res); 7121556Srgrimes } 7138855Srgrimes 7148855Srgrimes if (res == 0) 7151556Srgrimes warn(0, "End of archive volume %d reached", arvol); 7161556Srgrimes else if (res < 0) 7171556Srgrimes syswarn(1, errno, "Failed write to archive volume: %d", arvol); 7181556Srgrimes else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0)) 7191556Srgrimes warn(0,"WARNING: partial archive write. Archive MAY BE FLAWED"); 7201556Srgrimes else 7211556Srgrimes warn(1,"WARNING: partial archive write. Archive IS FLAWED"); 7221556Srgrimes return(res); 7231556Srgrimes} 7241556Srgrimes 7251556Srgrimes/* 7261556Srgrimes * ar_rdsync() 7271556Srgrimes * Try to move past a bad spot on a flawed archive as needed to continue 7281556Srgrimes * I/O. Clears error flags to allow I/O to continue. 7291556Srgrimes * Return: 7301556Srgrimes * 0 when ok to try i/o again, -1 otherwise. 7311556Srgrimes */ 7321556Srgrimes 7331556Srgrimes#if __STDC__ 7341556Srgrimesint 7351556Srgrimesar_rdsync(void) 7361556Srgrimes#else 7371556Srgrimesint 7381556Srgrimesar_rdsync() 7391556Srgrimes#endif 7401556Srgrimes{ 7411556Srgrimes long fsbz; 7421556Srgrimes off_t cpos; 7431556Srgrimes off_t mpos; 7441556Srgrimes struct mtop mb; 7451556Srgrimes 7461556Srgrimes /* 7471556Srgrimes * Fail resync attempts at user request (done) or this is going to be 7481556Srgrimes * an update/append to a existing archive. if last i/o hit media end, 7491556Srgrimes * we need to go to the next volume not try a resync 7501556Srgrimes */ 7511556Srgrimes if ((done > 0) || (lstrval == 0)) 7521556Srgrimes return(-1); 7531556Srgrimes 7541556Srgrimes if ((act == APPND) || (act == ARCHIVE)) { 7551556Srgrimes warn(1, "Cannot allow updates to an archive with flaws."); 7561556Srgrimes return(-1); 7571556Srgrimes } 7581556Srgrimes if (io_ok) 7591556Srgrimes did_io = 1; 7601556Srgrimes 7611556Srgrimes switch(artyp) { 7621556Srgrimes case ISTAPE: 7631556Srgrimes /* 7641556Srgrimes * if the last i/o was a successful data transfer, we assume 7651556Srgrimes * the fault is just a bad record on the tape that we are now 7661556Srgrimes * past. If we did not get any data since the last resync try 7671556Srgrimes * to move the tape foward one PHYSICAL record past any 7681556Srgrimes * damaged tape section. Some tape drives are stubborn and need 7691556Srgrimes * to be pushed. 7701556Srgrimes */ 7711556Srgrimes if (io_ok) { 7721556Srgrimes io_ok = 0; 7731556Srgrimes lstrval = 1; 7741556Srgrimes break; 7751556Srgrimes } 7761556Srgrimes mb.mt_op = MTFSR; 7771556Srgrimes mb.mt_count = 1; 7781556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) 7791556Srgrimes break; 7801556Srgrimes lstrval = 1; 7811556Srgrimes break; 7821556Srgrimes case ISREG: 7831556Srgrimes case ISCHR: 7841556Srgrimes case ISBLK: 7851556Srgrimes /* 7861556Srgrimes * try to step over the bad part of the device. 7871556Srgrimes */ 7881556Srgrimes io_ok = 0; 7891556Srgrimes if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) 7901556Srgrimes fsbz = BLKMULT; 7911556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) 7921556Srgrimes break; 7931556Srgrimes mpos = fsbz - (cpos % (off_t)fsbz); 7948855Srgrimes if (lseek(arfd, mpos, SEEK_CUR) < 0) 7951556Srgrimes break; 7961556Srgrimes lstrval = 1; 7971556Srgrimes break; 7981556Srgrimes case ISPIPE: 7991556Srgrimes default: 8001556Srgrimes /* 8011556Srgrimes * cannot recover on these archive device types 8021556Srgrimes */ 8031556Srgrimes io_ok = 0; 8041556Srgrimes break; 8051556Srgrimes } 8061556Srgrimes if (lstrval <= 0) { 8071556Srgrimes warn(1, "Unable to recover from an archive read failure."); 8081556Srgrimes return(-1); 8091556Srgrimes } 8101556Srgrimes warn(0, "Attempting to recover from an archive read failure."); 8111556Srgrimes return(0); 8121556Srgrimes} 8131556Srgrimes 8141556Srgrimes/* 8151556Srgrimes * ar_fow() 8161556Srgrimes * Move the I/O position within the archive foward the specified number of 8171556Srgrimes * bytes as supported by the device. If we cannot move the requested 8181556Srgrimes * number of bytes, return the actual number of bytes moved in skipped. 8191556Srgrimes * Return: 8201556Srgrimes * 0 if moved the requested distance, -1 on complete failure, 1 on 8211556Srgrimes * partial move (the amount moved is in skipped) 8221556Srgrimes */ 8231556Srgrimes 8241556Srgrimes#if __STDC__ 8251556Srgrimesint 8261556Srgrimesar_fow(off_t sksz, off_t *skipped) 8271556Srgrimes#else 8281556Srgrimesint 8291556Srgrimesar_fow(sksz, skipped) 8301556Srgrimes off_t sksz; 8311556Srgrimes off_t *skipped; 8321556Srgrimes#endif 8331556Srgrimes{ 8341556Srgrimes off_t cpos; 8351556Srgrimes off_t mpos; 8361556Srgrimes 8371556Srgrimes *skipped = 0; 8381556Srgrimes if (sksz <= 0) 8391556Srgrimes return(0); 8401556Srgrimes 8411556Srgrimes /* 8421556Srgrimes * we cannot move foward at EOF or error 8431556Srgrimes */ 8441556Srgrimes if (lstrval <= 0) 8451556Srgrimes return(lstrval); 8461556Srgrimes 8471556Srgrimes /* 8481556Srgrimes * Safer to read forward on devices where it is hard to find the end of 8491556Srgrimes * the media without reading to it. With tapes we cannot be sure of the 8501556Srgrimes * number of physical blocks to skip (we do not know physical block 8511556Srgrimes * size at this point), so we must only read foward on tapes! 8521556Srgrimes */ 8538855Srgrimes if (artyp != ISREG) 8541556Srgrimes return(0); 8551556Srgrimes 8561556Srgrimes /* 8571556Srgrimes * figure out where we are in the archive 8581556Srgrimes */ 8591556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) { 8608855Srgrimes /* 8611556Srgrimes * we can be asked to move farther than there are bytes in this 8621556Srgrimes * volume, if so, just go to file end and let normal buf_fill() 8631556Srgrimes * deal with the end of file (it will go to next volume by 8641556Srgrimes * itself) 8651556Srgrimes */ 8661556Srgrimes if ((mpos = cpos + sksz) > arsb.st_size) { 8671556Srgrimes *skipped = arsb.st_size - cpos; 8681556Srgrimes mpos = arsb.st_size; 8691556Srgrimes } else 8701556Srgrimes *skipped = sksz; 8711556Srgrimes if (lseek(arfd, mpos, SEEK_SET) >= 0) 8721556Srgrimes return(0); 8731556Srgrimes } 8741556Srgrimes syswarn(1, errno, "Foward positioning operation on archive failed"); 8751556Srgrimes lstrval = -1; 8761556Srgrimes return(-1); 8771556Srgrimes} 8781556Srgrimes 8791556Srgrimes/* 8801556Srgrimes * ar_rev() 8811556Srgrimes * move the i/o position within the archive backwards the specified byte 8821556Srgrimes * count as supported by the device. With tapes drives we RESET rdblksz to 8831556Srgrimes * the PHYSICAL blocksize. 8841556Srgrimes * NOTE: We should only be called to move backwards so we can rewrite the 8851556Srgrimes * last records (the trailer) of an archive (APPEND). 8861556Srgrimes * Return: 8871556Srgrimes * 0 if moved the requested distance, -1 on complete failure 8881556Srgrimes */ 8891556Srgrimes 8901556Srgrimes#if __STDC__ 8911556Srgrimesint 8921556Srgrimesar_rev(off_t sksz) 8931556Srgrimes#else 8941556Srgrimesint 8951556Srgrimesar_rev(sksz) 8961556Srgrimes off_t sksz; 8971556Srgrimes#endif 8981556Srgrimes{ 8991556Srgrimes off_t cpos; 9001556Srgrimes struct mtop mb; 9018855Srgrimes register int phyblk; 9021556Srgrimes 9031556Srgrimes /* 9041556Srgrimes * make sure we do not have try to reverse on a flawed archive 9051556Srgrimes */ 9061556Srgrimes if (lstrval < 0) 9071556Srgrimes return(lstrval); 9081556Srgrimes 9091556Srgrimes switch(artyp) { 9101556Srgrimes case ISPIPE: 9118855Srgrimes if (sksz <= 0) 9121556Srgrimes break; 9131556Srgrimes /* 9141556Srgrimes * cannot go backwards on these critters 9151556Srgrimes */ 9161556Srgrimes warn(1, "Reverse positioning on pipes is not supported."); 9171556Srgrimes lstrval = -1; 9181556Srgrimes return(-1); 9191556Srgrimes case ISREG: 9201556Srgrimes case ISBLK: 9211556Srgrimes case ISCHR: 9221556Srgrimes default: 9231556Srgrimes if (sksz <= 0) 9241556Srgrimes break; 9251556Srgrimes 9261556Srgrimes /* 9271556Srgrimes * For things other than files, backwards movement has a very 9281556Srgrimes * high probability of failure as we really do not know the 9291556Srgrimes * true attributes of the device we are talking to (the device 9301556Srgrimes * may not even have the ability to lseek() in any direction). 9311556Srgrimes * First we figure out where we are in the archive. 9321556Srgrimes */ 9331556Srgrimes if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) { 9341556Srgrimes syswarn(1, errno, 9351556Srgrimes "Unable to obtain current archive byte offset"); 9361556Srgrimes lstrval = -1; 9371556Srgrimes return(-1); 9381556Srgrimes } 9391556Srgrimes 9401556Srgrimes /* 9411556Srgrimes * we may try to go backwards past the start when the archive 9421556Srgrimes * is only a single record. If this hapens and we are on a 9431556Srgrimes * multi volume archive, we need to go to the end of the 9441556Srgrimes * previous volume and continue our movement backwards from 9451556Srgrimes * there. 9461556Srgrimes */ 9471556Srgrimes if ((cpos -= sksz) < (off_t)0L) { 9481556Srgrimes if (arvol > 1) { 9491556Srgrimes /* 9501556Srgrimes * this should never happen 9511556Srgrimes */ 9521556Srgrimes warn(1,"Reverse position on previous volume."); 9531556Srgrimes lstrval = -1; 9541556Srgrimes return(-1); 9551556Srgrimes } 9561556Srgrimes cpos = (off_t)0L; 9571556Srgrimes } 9581556Srgrimes if (lseek(arfd, cpos, SEEK_SET) < 0) { 9591556Srgrimes syswarn(1, errno, "Unable to seek archive backwards"); 9601556Srgrimes lstrval = -1; 9611556Srgrimes return(-1); 9621556Srgrimes } 9631556Srgrimes break; 9641556Srgrimes case ISTAPE: 9651556Srgrimes /* 9661556Srgrimes * Calculate and move the proper number of PHYSICAL tape 9671556Srgrimes * blocks. If the sksz is not an even multiple of the physical 9681556Srgrimes * tape size, we cannot do the move (this should never happen). 9691556Srgrimes * (We also cannot handler trailers spread over two vols). 9701556Srgrimes * get_phys() also makes sure we are in front of the filemark. 9711556Srgrimes */ 9721556Srgrimes if ((phyblk = get_phys()) <= 0) { 9731556Srgrimes lstrval = -1; 9741556Srgrimes return(-1); 9751556Srgrimes } 9761556Srgrimes 9771556Srgrimes /* 9781556Srgrimes * make sure future tape reads only go by physical tape block 9791556Srgrimes * size (set rdblksz to the real size). 9801556Srgrimes */ 9811556Srgrimes rdblksz = phyblk; 9821556Srgrimes 9831556Srgrimes /* 9841556Srgrimes * if no movement is required, just return (we must be after 9851556Srgrimes * get_phys() so the physical blocksize is properly set) 9861556Srgrimes */ 9871556Srgrimes if (sksz <= 0) 9881556Srgrimes break; 9891556Srgrimes 9901556Srgrimes /* 9911556Srgrimes * ok we have to move. Make sure the tape drive can do it. 9921556Srgrimes */ 9931556Srgrimes if (sksz % phyblk) { 9941556Srgrimes warn(1, 9951556Srgrimes "Tape drive unable to backspace requested amount"); 9961556Srgrimes lstrval = -1; 9971556Srgrimes return(-1); 9981556Srgrimes } 9991556Srgrimes 10001556Srgrimes /* 10011556Srgrimes * move backwards the requested number of bytes 10021556Srgrimes */ 10031556Srgrimes mb.mt_op = MTBSR; 10041556Srgrimes mb.mt_count = sksz/phyblk; 10051556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 10061556Srgrimes syswarn(1,errno, "Unable to backspace tape %d blocks.", 10071556Srgrimes mb.mt_count); 10081556Srgrimes lstrval = -1; 10091556Srgrimes return(-1); 10101556Srgrimes } 10111556Srgrimes break; 10121556Srgrimes } 10131556Srgrimes lstrval = 1; 10141556Srgrimes return(0); 10151556Srgrimes} 10161556Srgrimes 10171556Srgrimes/* 10181556Srgrimes * get_phys() 10191556Srgrimes * Determine the physical block size on a tape drive. We need the physical 10208855Srgrimes * block size so we know how many bytes we skip over when we move with 10211556Srgrimes * mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when 10221556Srgrimes * return. 10231556Srgrimes * This is one really SLOW routine... 10241556Srgrimes * Return: 10251556Srgrimes * physical block size if ok (ok > 0), -1 otherwise 10261556Srgrimes */ 10271556Srgrimes 10281556Srgrimes#if __STDC__ 10291556Srgrimesstatic int 10301556Srgrimesget_phys(void) 10311556Srgrimes#else 10321556Srgrimesstatic int 10331556Srgrimesget_phys() 10341556Srgrimes#endif 10351556Srgrimes{ 10361556Srgrimes register int padsz = 0; 10371556Srgrimes register int res; 10381556Srgrimes register int phyblk; 10391556Srgrimes struct mtop mb; 10401556Srgrimes char scbuf[MAXBLK]; 10411556Srgrimes 10421556Srgrimes /* 10431556Srgrimes * move to the file mark, and then back up one record and read it. 10441556Srgrimes * this should tell us the physical record size the tape is using. 10451556Srgrimes */ 10461556Srgrimes if (lstrval == 1) { 10471556Srgrimes /* 10481556Srgrimes * we know we are at file mark when we get back a 0 from 10491556Srgrimes * read() 10501556Srgrimes */ 10511556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10521556Srgrimes padsz += res; 10531556Srgrimes if (res < 0) { 10541556Srgrimes syswarn(1, errno, "Unable to locate tape filemark."); 10551556Srgrimes return(-1); 10561556Srgrimes } 10571556Srgrimes } 10581556Srgrimes 10591556Srgrimes /* 10601556Srgrimes * move backwards over the file mark so we are at the end of the 10611556Srgrimes * last record. 10621556Srgrimes */ 10631556Srgrimes mb.mt_op = MTBSF; 10641556Srgrimes mb.mt_count = 1; 10651556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 10661556Srgrimes syswarn(1, errno, "Unable to backspace over tape filemark."); 10671556Srgrimes return(-1); 10681556Srgrimes } 10691556Srgrimes 10701556Srgrimes /* 10711556Srgrimes * move backwards so we are in front of the last record and read it to 10721556Srgrimes * get physical tape blocksize. 10731556Srgrimes */ 10741556Srgrimes mb.mt_op = MTBSR; 10751556Srgrimes mb.mt_count = 1; 10761556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 10771556Srgrimes syswarn(1, errno, "Unable to backspace over last tape block."); 10781556Srgrimes return(-1); 10791556Srgrimes } 10801556Srgrimes if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) { 10811556Srgrimes syswarn(1, errno, "Cannot determine archive tape blocksize."); 10821556Srgrimes return(-1); 10831556Srgrimes } 10841556Srgrimes 10851556Srgrimes /* 10861556Srgrimes * read foward to the file mark, then back up in front of the filemark 10871556Srgrimes * (this is a bit paranoid, but should be safe to do). 10881556Srgrimes */ 10891556Srgrimes while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) 10901556Srgrimes ; 10911556Srgrimes if (res < 0) { 10921556Srgrimes syswarn(1, errno, "Unable to locate tape filemark."); 10931556Srgrimes return(-1); 10941556Srgrimes } 10951556Srgrimes mb.mt_op = MTBSF; 10961556Srgrimes mb.mt_count = 1; 10971556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 10981556Srgrimes syswarn(1, errno, "Unable to backspace over tape filemark."); 10991556Srgrimes return(-1); 11001556Srgrimes } 11011556Srgrimes 11021556Srgrimes /* 11031556Srgrimes * set lstrval so we know that the filemark has not been seen 11041556Srgrimes */ 11051556Srgrimes lstrval = 1; 11061556Srgrimes 11071556Srgrimes /* 11081556Srgrimes * return if there was no padding 11091556Srgrimes */ 11101556Srgrimes if (padsz == 0) 11111556Srgrimes return(phyblk); 11121556Srgrimes 11131556Srgrimes /* 11141556Srgrimes * make sure we can move backwards over the padding. (this should 11151556Srgrimes * never fail). 11161556Srgrimes */ 11171556Srgrimes if (padsz % phyblk) { 11181556Srgrimes warn(1, "Tape drive unable to backspace requested amount"); 11191556Srgrimes return(-1); 11201556Srgrimes } 11211556Srgrimes 11221556Srgrimes /* 11231556Srgrimes * move backwards over the padding so the head is where it was when 11241556Srgrimes * we were first called (if required). 11251556Srgrimes */ 11261556Srgrimes mb.mt_op = MTBSR; 11271556Srgrimes mb.mt_count = padsz/phyblk; 11281556Srgrimes if (ioctl(arfd, MTIOCTOP, &mb) < 0) { 11291556Srgrimes syswarn(1,errno,"Unable to backspace tape over %d pad blocks", 11301556Srgrimes mb.mt_count); 11311556Srgrimes return(-1); 11321556Srgrimes } 11331556Srgrimes return(phyblk); 11341556Srgrimes} 11351556Srgrimes 11361556Srgrimes/* 11371556Srgrimes * ar_next() 11381556Srgrimes * prompts the user for the next volume in this archive. For some devices 11391556Srgrimes * we may allow the media to be changed. Otherwise a new archive is 11401556Srgrimes * prompted for. By pax spec, if there is no controlling tty or an eof is 11411556Srgrimes * read on tty input, we must quit pax. 11421556Srgrimes * Return: 11431556Srgrimes * 0 when ready to continue, -1 when all done 11441556Srgrimes */ 11451556Srgrimes 11461556Srgrimes#if __STDC__ 11471556Srgrimesint 11481556Srgrimesar_next(void) 11491556Srgrimes#else 11501556Srgrimesint 11511556Srgrimesar_next() 11521556Srgrimes#endif 11531556Srgrimes{ 11541556Srgrimes char buf[PAXPATHLEN+2]; 11551556Srgrimes static int freeit = 0; 11561556Srgrimes sigset_t o_mask; 11571556Srgrimes 11581556Srgrimes /* 11591556Srgrimes * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so 11601556Srgrimes * things like writing EOF etc will be done) (Watch out ar_close() can 11611556Srgrimes * also be called via a signal handler, so we must prevent a race. 11621556Srgrimes */ 11631556Srgrimes if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0) 11641556Srgrimes syswarn(0, errno, "Unable to set signal mask"); 11651556Srgrimes ar_close(); 11661556Srgrimes if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0) 11671556Srgrimes syswarn(0, errno, "Unable to restore signal mask"); 11681556Srgrimes 11691556Srgrimes if (done || !wr_trail) 11701556Srgrimes return(-1); 11711556Srgrimes 11721556Srgrimes tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0); 11731556Srgrimes 11741556Srgrimes /* 11751556Srgrimes * if i/o is on stdin or stdout, we cannot reopen it (we do not know 11761556Srgrimes * the name), the user will be forced to type it in. 11771556Srgrimes */ 11781556Srgrimes if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG) 11791556Srgrimes && (artyp != ISPIPE)) { 11801556Srgrimes if (artyp == ISTAPE) { 11811556Srgrimes tty_prnt("%s ready for archive tape volume: %d\n", 11821556Srgrimes arcname, arvol); 11831556Srgrimes tty_prnt("Load the NEXT TAPE on the tape drive"); 11841556Srgrimes } else { 11851556Srgrimes tty_prnt("%s ready for archive volume: %d\n", 11861556Srgrimes arcname, arvol); 11871556Srgrimes tty_prnt("Load the NEXT STORAGE MEDIA (if required)"); 11881556Srgrimes } 11891556Srgrimes 11901556Srgrimes if ((act == ARCHIVE) || (act == APPND)) 11911556Srgrimes tty_prnt(" and make sure it is WRITE ENABLED.\n"); 11921556Srgrimes else 11931556Srgrimes tty_prnt("\n"); 11941556Srgrimes 11951556Srgrimes for(;;) { 11961556Srgrimes tty_prnt("Type \"y\" to continue, \".\" to quit %s,", 11971556Srgrimes argv0); 11981556Srgrimes tty_prnt(" or \"s\" to switch to new device.\nIf you"); 11991556Srgrimes tty_prnt(" cannot change storage media, type \"s\"\n"); 12001556Srgrimes tty_prnt("Is the device ready and online? > "); 12011556Srgrimes 12021556Srgrimes if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){ 12031556Srgrimes done = 1; 12041556Srgrimes lstrval = -1; 12051556Srgrimes tty_prnt("Quitting %s!\n", argv0); 12061556Srgrimes vfpart = 0; 12071556Srgrimes return(-1); 12081556Srgrimes } 12091556Srgrimes 12101556Srgrimes if ((buf[0] == '\0') || (buf[1] != '\0')) { 12111556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 12121556Srgrimes continue; 12131556Srgrimes } 12141556Srgrimes 12151556Srgrimes switch (buf[0]) { 12161556Srgrimes case 'y': 12171556Srgrimes case 'Y': 12181556Srgrimes /* 12191556Srgrimes * we are to continue with the same device 12201556Srgrimes */ 12218855Srgrimes if (ar_open(arcname) >= 0) 12221556Srgrimes return(0); 12231556Srgrimes tty_prnt("Cannot re-open %s, try again\n", 12241556Srgrimes arcname); 12251556Srgrimes continue; 12261556Srgrimes case 's': 12271556Srgrimes case 'S': 12281556Srgrimes /* 12291556Srgrimes * user wants to open a different device 12301556Srgrimes */ 12311556Srgrimes tty_prnt("Switching to a different archive\n"); 12321556Srgrimes break; 12331556Srgrimes default: 12341556Srgrimes tty_prnt("%s unknown command, try again\n",buf); 12351556Srgrimes continue; 12361556Srgrimes } 12371556Srgrimes break; 12381556Srgrimes } 12391556Srgrimes } else 12401556Srgrimes tty_prnt("Ready for archive volume: %d\n", arvol); 12411556Srgrimes 12421556Srgrimes /* 12431556Srgrimes * have to go to a different archive 12441556Srgrimes */ 12451556Srgrimes for (;;) { 12461556Srgrimes tty_prnt("Input archive name or \".\" to quit %s.\n", argv0); 12471556Srgrimes tty_prnt("Archive name > "); 12481556Srgrimes 12491556Srgrimes if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) { 12501556Srgrimes done = 1; 12511556Srgrimes lstrval = -1; 12521556Srgrimes tty_prnt("Quitting %s!\n", argv0); 12531556Srgrimes vfpart = 0; 12541556Srgrimes return(-1); 12551556Srgrimes } 12561556Srgrimes if (buf[0] == '\0') { 12571556Srgrimes tty_prnt("Empty file name, try again\n"); 12581556Srgrimes continue; 12591556Srgrimes } 12601556Srgrimes if (!strcmp(buf, "..")) { 12611556Srgrimes tty_prnt("Illegal file name: .. try again\n"); 12621556Srgrimes continue; 12631556Srgrimes } 12641556Srgrimes if (strlen(buf) > PAXPATHLEN) { 12651556Srgrimes tty_prnt("File name too long, try again\n"); 12661556Srgrimes continue; 12671556Srgrimes } 12681556Srgrimes 12691556Srgrimes /* 12701556Srgrimes * try to open new archive 12711556Srgrimes */ 12721556Srgrimes if (ar_open(buf) >= 0) { 12731556Srgrimes if (freeit) { 12741556Srgrimes (void)free(arcname); 12751556Srgrimes freeit = 0; 12761556Srgrimes } 12771556Srgrimes if ((arcname = strdup(buf)) == NULL) { 12781556Srgrimes done = 1; 12791556Srgrimes lstrval = -1; 12801556Srgrimes warn(0, "Cannot save archive name."); 12811556Srgrimes return(-1); 12821556Srgrimes } 12831556Srgrimes freeit = 1; 12841556Srgrimes break; 12851556Srgrimes } 12861556Srgrimes tty_prnt("Cannot open %s, try again\n", buf); 12871556Srgrimes continue; 12881556Srgrimes } 12891556Srgrimes return(0); 12901556Srgrimes} 1291