int rmtopen(char *tape, int mode) { struct mtget mt; char buf[256]; int fd; (void) snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode); rmtstate = TS_OPEN; fd = rmtcall(tape, buf); if (fd != -1) { /* see if the rmt server supports the extended protocol */ rmtversion = rmtioctl(-1, 0); /* * Some rmt daemons apparently close the connection * when they get a bogus ioctl. See 1210852 (ignore * the evaluation). Make sure we can still talk to * the device, re-opening it if necessary. */ if (rmtversion < 1) { if (rmtstatus(&mt) < 0) { rmtclose(); rmtgetconn(); rmtversion = 0; } } } return (fd); }
void _rmtclose(void) { #ifdef RMT if (host) rmtclose(); #endif }
void closemt(void) { if (mt < 0) return; #ifdef RRESTORE if (host) rmtclose(); else #endif (void)close(mt); }
void closemt(void) { if (mt < 0) return; if (pipecmdin) { pclose(popenfp); popenfp = NULL; } else #ifdef RRESTORE if (host) rmtclose(); else #endif (void) close(mt); }
/* * ar_close() * closes archive device, increments volume number, and prints i/o summary */ void ar_close(void) { int status; if (arfd < 0) { did_io = io_ok = flcnt = 0; return; } /* * Close archive file. This may take a LONG while on tapes (we may be * forced to wait for the rewind to complete) so tell the user what is * going on (this avoids the user hitting control-c thinking pax is * broken). */ if ((vflag || Vflag) && (artyp == ISTAPE)) { if (vfpart) (void)putc('\n', listf); (void)fprintf(listf, "%s: Waiting for tape drive close to complete...", argv0); (void)fflush(listf); } /* * if nothing was written to the archive (and we created it), we remove * it */ if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && (arsb.st_size == 0)) { (void)unlink(arcname); can_unlnk = 0; } /* * for a quick extract/list, pax frequently exits before the child * process is done */ if ((act == LIST || act == EXTRACT) && nflag && zpid > 0) kill(zpid, SIGINT); #ifdef SUPPORT_RMT if (artyp == ISRMT) (void)rmtclose(arfd); else #endif /* SUPPORT_RMT */ (void)close(arfd); /* Do not exit before child to ensure data integrity */ if (zpid > 0) waitpid(zpid, &status, 0); if ((vflag || Vflag) && (artyp == ISTAPE)) { (void)fputs("done.\n", listf); vfpart = 0; (void)fflush(listf); } arfd = -1; if (!io_ok && !did_io) { flcnt = 0; return; } did_io = io_ok = 0; /* * The volume number is only increased when the last device has data * and we have already determined the archive format. */ if (frmt != NULL) ++arvol; if (!vflag && !Vflag) { flcnt = 0; return; } /* * Print out a summary of I/O for this archive volume. */ if (vfpart) { (void)putc('\n', listf); vfpart = 0; } /* mimic cpio's block count first */ if (frmt && strcmp(NM_CPIO, argv0) == 0) { (void)fprintf(listf, OFFT_F " blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120); } ar_summary(0); (void)fflush(listf); flcnt = 0; }
int ar_open(const char *name) { #ifdef HAVE_SYS_MTIO_H struct mtget mb; #endif if (arfd != -1) (void)close(arfd); arfd = -1; can_unlnk = did_io = io_ok = invld_rec = 0; artyp = ISREG; flcnt = 0; #ifdef SUPPORT_RMT if (name && strchr(name, ':') != NULL && !forcelocal) { artyp = ISRMT; if ((arfd = rmtopen(name, O_RDWR, DMOD)) == -1) { syswarn(0, errno, "Failed open on %s", name); return -1; } if (!isrmt(arfd)) { rmtclose(arfd); tty_warn(0, "Not a remote file: %s", name); return -1; } blksz = rdblksz = 8192; lstrval = 1; return 0; } #endif /* SUPPORT_RMT */ /* * open based on overall operation mode */ switch (act) { case LIST: case EXTRACT: if (name == NULL) { arfd = STDIN_FILENO; arcname = STDN; } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) syswarn(0, errno, "Failed open to read on %s", name); if (arfd != -1 && gzip_program != NULL) ar_start_gzip(arfd, gzip_program, 0); break; case ARCHIVE: if (name == NULL) { arfd = STDOUT_FILENO; arcname = STDO; } else if ((arfd = open(name, AR_MODE, DMOD)) < 0) syswarn(0, errno, "Failed open to write on %s", name); else can_unlnk = 1; if (arfd != -1 && gzip_program != NULL) ar_start_gzip(arfd, gzip_program, 1); break; case APPND: if (name == NULL) { arfd = STDOUT_FILENO; arcname = STDO; } else if ((arfd = open(name, APP_MODE, DMOD)) < 0) syswarn(0, errno, "Failed open to read/write on %s", name); break; case COPY: /* * arfd not used in COPY mode */ arcname = NONE; lstrval = 1; return 0; } if (arfd < 0) return -1; if (chdname != NULL) if (dochdir(chdname) == -1) return -1; /* * set up is based on device type */ if (fstat(arfd, &arsb) < 0) { syswarn(0, errno, "Failed stat on %s", arcname); (void)close(arfd); arfd = -1; can_unlnk = 0; return -1; } if (S_ISDIR(arsb.st_mode)) { tty_warn(0, "Cannot write an archive on top of a directory %s", arcname); (void)close(arfd); arfd = -1; can_unlnk = 0; return -1; } if (S_ISCHR(arsb.st_mode)) { #ifdef HAVE_SYS_MTIO_H artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; #else tty_warn(1, "System does not have tape support"); artyp = ISREG; #endif } else if (S_ISBLK(arsb.st_mode)) artyp = ISBLK; else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) artyp = ISPIPE; else artyp = ISREG; /* * Special handling for empty files. */ if (artyp == ISREG && arsb.st_size == 0) { switch (act) { case LIST: case EXTRACT: return -1; case APPND: act = -ARCHIVE; return -1; case ARCHIVE: break; } } /* * make sure we beyond any doubt that we only can unlink regular files * we created */ if (artyp != ISREG) can_unlnk = 0; /* * if we are writing, we are done */ if (act == ARCHIVE) { blksz = rdblksz = wrblksz; lstrval = 1; return 0; } /* * set default blksz on read. APPNDs writes rdblksz on the last volume * On all new archive volumes, we shift to wrblksz (if the user * specified one, otherwize we will continue to use rdblksz). We * must set blocksize based on what kind of device the archive is * stored. */ switch(artyp) { case ISTAPE: /* * Tape drives come in at least two flavors. Those that support * variable sized records and those that have fixed sized * records. They must be treated differently. For tape drives * that support variable sized records, we must make large * reads to make sure we get the entire record, otherwise we * will just get the first part of the record (up to size we * asked). Tapes with fixed sized records may or may not return * multiple records in a single read. We really do not care * what the physical record size is UNLESS we are going to * append. (We will need the physical block size to rewrite * the trailer). Only when we are appending do we go to the * effort to figure out the true PHYSICAL record size. */ blksz = rdblksz = MAXBLK; break; case ISPIPE: case ISBLK: case ISCHR: /* * Blocksize is not a major issue with these devices (but must * be kept a multiple of 512). If the user specified a write * block size, we use that to read. Under append, we must * always keep blksz == rdblksz. Otherwise we go ahead and use * the device optimal blocksize as (and if) returned by stat * and if it is within pax specs. */ if ((act == APPND) && wrblksz) { blksz = rdblksz = wrblksz; break; } if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && ((arsb.st_blksize % BLKMULT) == 0)) rdblksz = arsb.st_blksize; else rdblksz = DEVBLK; /* * For performance go for large reads when we can without harm */ if ((act == APPND) || (artyp == ISCHR)) blksz = rdblksz; else blksz = MAXBLK; break; case ISREG: /* * if the user specified wrblksz works, use it. Under appends * we must always keep blksz == rdblksz */ if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ blksz = rdblksz = wrblksz; break; } /* * See if we can find the blocking factor from the file size */ for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) if ((arsb.st_size % rdblksz) == 0) break; /* * When we cannot find a match, we may have a flawed archive. */ if (rdblksz <= 0) rdblksz = FILEBLK; /* * for performance go for large reads when we can */ if (act == APPND) blksz = rdblksz; else blksz = MAXBLK; break; default: /* * should never happen, worst case, slow... */ blksz = rdblksz = BLKMULT; break; } lstrval = 1; return 0; }