/* * Rmtisatty. Do the isatty function. */ int rmtisatty(int fd) { if (isrmt(fd)) return 0; else return isatty(fd); }
/* * Close a file. Looks just like close(2) to caller. */ int rmtclose(int fildes) { if (isrmt(fildes)) { return _rmt_close(fildes - REM_BIAS); } else { return close(fildes); } }
/* * Perform lseek on file. Looks just like lseek(2) to caller. */ off_t rmtlseek(int fildes, off_t offset, int whence) { if (isrmt(fildes)) { return _rmt_lseek(fildes - REM_BIAS, offset, whence); } else { return lseek(fildes, offset, whence); } }
/* * Duplicate an open file descriptor. Looks just like dup(2) * to caller. */ int rmtdup(int fildes) { if (isrmt(fildes)) { errno = EOPNOTSUPP; return -1; /* For now (fnf) */ } else { return dup(fildes); } }
/* * Write to stream. Looks just like write(2) to caller. */ ssize_t rmtwrite(int fildes, const void *buf, size_t nbyte) { _DIAGASSERT(buf != NULL); if (isrmt(fildes)) { return _rmt_write(fildes - REM_BIAS, buf, nbyte); } else { return write(fildes, buf, nbyte); } }
/* * Read from stream. Looks just like read(2) to caller. */ ssize_t rmtread(int fildes, void *buf, size_t nbyte) { _DIAGASSERT(buf != NULL); if (isrmt(fildes)) { return _rmt_read(fildes - REM_BIAS, buf, nbyte); } else { return read(fildes, buf, nbyte); } }
/* * Get file status. Looks just like fstat(2) to caller. */ int rmtfstat(int fildes, struct stat *buf) { _DIAGASSERT(buf != NULL); if (isrmt(fildes)) { errno = EOPNOTSUPP; return -1; /* For now (fnf) */ } else { return fstat(fildes, buf); } }
/* * Rmtfcntl. Do a remote fcntl operation. */ int rmtfcntl(int fd, int cmd, ...) { void *arg; va_list ap; va_start(ap, cmd); arg = va_arg(ap, void *); va_end(ap); /* XXX: arg may be NULL ? */ if (isrmt(fd)) { errno = EOPNOTSUPP; return -1; } else { return fcntl(fd, cmd, arg); } }
/* * Do ioctl on file. Looks just like ioctl(2) to caller. */ int rmtioctl(int fildes, unsigned long request, ...) { void *arg; va_list ap; va_start(ap, request); arg = va_arg(ap, void *); va_end(ap); /* XXX: arg may be NULL ? */ if (isrmt(fildes)) { #ifdef RMTIOCTL return _rmt_ioctl(fildes - REM_BIAS, request, arg); #else errno = EOPNOTSUPP; return -1; /* For now (fnf) */ #endif } else { return ioctl(fildes, request, arg); } }
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; }