From d1925e0c515fcb4f815d75292566d600fd715ff5 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Sun, 26 Oct 2003 16:05:44 +0000 Subject: [PATCH] From Uwe Gohlke: * compile under Solaris * restore MacOSX made dumps * made rmt work with local/remote QFA. --- CHANGES | 17 +- common/dumprmt.c | 46 ++- compat/include/bsdcompat.h | 46 ++- compat/include/pathnames.h | 7 +- compat/include/protocols/dumprestore.h | 28 +- compat/lib/bylabel.c | 2 + compat/lib/compaterr.c | 3 +- compat/lib/compatglob.c | 5 +- config.h.in | 3 + configure | 22 ++ configure.in | 17 + dump/dump.h | 11 +- dump/itime.c | 3 +- dump/main.c | 50 ++- dump/tape.c | 82 ++++- dump/traverse.c | 6 +- restore/dirs.c | 27 +- restore/extern.h | 23 +- restore/interactive.c | 11 +- restore/main.c | 56 ++- restore/restore.c | 122 +++++-- restore/restore.h | 7 +- restore/symtab.c | 7 +- restore/tape.c | 482 +++++++++++++++++++++++-- restore/utilities.c | 198 +++++++++- rmt/rmt.c | 159 ++++++-- 26 files changed, 1254 insertions(+), 186 deletions(-) diff --git a/CHANGES b/CHANGES index 06baed2..8a16dfa 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -$Id: CHANGES,v 1.232 2003/09/03 15:00:21 stelian Exp $ +$Id: CHANGES,v 1.233 2003/10/26 16:05:44 stelian Exp $ Changes between versions 0.4b34 and 0.4b35 (released ??????????????) ==================================================================== @@ -22,6 +22,21 @@ Changes between versions 0.4b34 and 0.4b35 (released ??????????????) different signature. Thanks to Mike Harris for reporting this bug. +5. Made dump/restore build on Solaris, making possible to + restore Linux's "enhanced" tapes. Thanks to Uwe Gohlke + for the patch. + +6. Made an extension in the dump tape format capable of saving + MacOSX specific inode extensions. Uwe Gohlke + wrote the extension and contributed the restore code back + into this codebase. The same extension mechanism will be + used in the future to save ACLs... + +7. Made rmt work correctly with regard to QFA and local/remote + files and tapes. The remote access will however work only + when the dump provided rmt version is used. If you want to + use another rmt server, please do not use the QFA feature. + Changes between versions 0.4b33 and 0.4b34 (released April 18, 2003) ==================================================================== diff --git a/common/dumprmt.c b/common/dumprmt.c index eb61a55..7f88f63 100644 --- a/common/dumprmt.c +++ b/common/dumprmt.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: dumprmt.c,v 1.27 2003/03/30 15:40:33 stelian Exp $"; + "$Id: dumprmt.c,v 1.28 2003/10/26 16:05:45 stelian Exp $"; #endif /* not lint */ #include @@ -114,6 +114,8 @@ int krcmd __P((char **, int /*u_short*/, char *, char *, int *, char *)); static int errfd = -1; extern int dokerberos; extern int ntrec; /* blocking factor on tape */ +extern int abortifconnerr; /* set to 1 if this lib should exit on connection errors + otherwise just print a message using msg */ #ifndef errno extern int errno; #endif @@ -152,8 +154,8 @@ rmtconnaborted(UNUSED(int signo)) } } } - - exit(X_ABORT); + if (abortifconnerr) + exit(X_ABORT); } static int @@ -174,20 +176,36 @@ rmtgetconn(void) if (!rsh && sp == NULL) { sp = getservbyname(dokerberos ? "kshell" : "shell", "tcp"); - if (sp == NULL) - errx(1, "%s/tcp: unknown service", - dokerberos ? "kshell" : "shell"); + if (sp == NULL) { + if (abortifconnerr) { + errx(1, "%s/tcp: unknown service", dokerberos ? "kshell" : "shell"); + } else { + msg("%s/tcp: unknown service", dokerberos ? "kshell" : "shell"); + return 0; + } + } } if (pwd == NULL) { pwd = getpwuid(getuid()); - if (pwd == NULL) - errx(1, "who are you?"); + if (pwd == NULL) { + if (abortifconnerr) { + errx(1, "who are you?"); + } else { + msg("who are you?"); + return 0; + } + } } if ((cp = strchr(rmtpeer, '@')) != NULL) { tuser = rmtpeer; *cp = '\0'; - if (!okname(tuser)) - exit(X_STARTUP); + if (!okname(tuser)) { + if (abortifconnerr) { + exit(X_STARTUP); + } else { + return 0; + } + } rmtpeer = ++cp; } else tuser = pwd->pw_name; @@ -250,7 +268,7 @@ rmtgetconn(void) perror("TCP_NODELAY setsockopt"); fromrmtape = tormtape; } - (void)fprintf(stderr, "Connection to %s established.\n", rmtpeer); + (void)fprintf(stdout, "Connection to %s established.\n", rmtpeer); return 1; } @@ -305,9 +323,11 @@ rmtread(char *buf, size_t count) (void)snprintf(line, sizeof (line), "R%u\n", (unsigned)count); n = rmtcall("read", line); - if (n < 0) + if (n < 0) { /* rmtcall() properly sets errno for us on errors. */ - return (n); + errno = n; + return (-1); + } for (i = 0; i < n; i += cc) { cc = read(fromrmtape, buf+i, n - i); if (cc <= 0) diff --git a/compat/include/bsdcompat.h b/compat/include/bsdcompat.h index ecb102f..0edf00d 100644 --- a/compat/include/bsdcompat.h +++ b/compat/include/bsdcompat.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: bsdcompat.h,v 1.19 2002/07/19 14:57:39 stelian Exp $ + * $Id: bsdcompat.h,v 1.20 2003/10/26 16:05:46 stelian Exp $ */ #include @@ -26,8 +26,13 @@ #define WINO 1 #define DEV_BSIZE 512 #define DEV_BSHIFT 9 + +#ifndef sunos #define MAXBSIZE EXT2_MAX_BLOCK_SIZE #define ROOTINO EXT2_ROOT_INO +#else +#define ROOTINO 2 +#endif #ifdef EXT2_NODUMP_FL #define UF_NODUMP EXT2_NODUMP_FL #endif @@ -36,7 +41,6 @@ #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #define powerof2(x) ((((x)-1)&(x))==0) -#define dbtob(b) ((unsigned)(b) << DEV_BSHIFT) #define fsbtodb(sb,b) ((int)(((long long)(b) * EXT2_BLOCK_SIZE((sb)->super)) / DEV_BSIZE)) #define dbtofsb(sb,b) ((int)(((long long)(b) * DEV_BSIZE) / EXT2_BLOCK_SIZE((sb)->super))) @@ -75,6 +79,25 @@ typedef __u64 u_quad_t; #define NINDIR(fs) EXT2_ADDR_PER_BLOCK(fs->super) +#ifdef sunos +typedef uint8_t __u8; +typedef uint16_t __u16; +typedef uint32_t __u32; +typedef int8_t __s8; +typedef int16_t __s16; +typedef int32_t __s32; +#ifndef u_int +#typedef unsigned int u_int; +#endif +#ifndef u_int16_t +typedef unsigned short u_int16_t; +#endif +#ifndef u_char +typedef unsigned char u_char; +#endif +typedef int64_t quad_t; +#endif /* sunos */ + struct dinode { __u16 di_mode; __u16 di_uid; @@ -118,6 +141,10 @@ struct dinode { #define MAXNAMLEN 255 #endif +#ifdef sunos +#define MAXNAMLEN 255 +#endif + /* * For old libc. */ @@ -130,6 +157,10 @@ struct dinode { #define DT_REG 8 #define DT_LNK 10 #define DT_SOCK 12 + +#ifdef sunos +#define DT_WHT 14 +#endif #endif #ifndef d_fileno @@ -158,20 +189,23 @@ struct direct { * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ +#ifdef __linux__ #if 0 #if (BYTE_ORDER == LITTLE_ENDIAN) #define DIRSIZ(oldfmt, dp) \ ((oldfmt) ? \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) -#else +#else /* BYTE_ORDER */ #define DIRSIZ(oldfmt, dp) \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) #endif -#else - +#else /* 0 */ #define DIRSIZ(oldfmt,dp) EXT2_DIR_REC_LEN(((dp)->d_namlen & 0xff) + 1) - +#endif +#else /* __linux__ */ +#define DIRSIZ(oldfmt, dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) #endif /* diff --git a/compat/include/pathnames.h b/compat/include/pathnames.h index afaa14d..281d204 100644 --- a/compat/include/pathnames.h +++ b/compat/include/pathnames.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: pathnames.h,v 1.13 2003/03/30 15:40:34 stelian Exp $ + * $Id: pathnames.h,v 1.14 2003/10/26 16:05:46 stelian Exp $ */ /* @@ -46,7 +46,12 @@ #endif #ifndef _PATH_DEFTAPE +#ifdef __linux__ #define _PATH_DEFTAPE "/dev/st0" #endif +#ifdef sunos +#define _PATH_DEFTAPE "/dev/rmt/0" +#endif +#endif #define _PATH_RMT "/etc/rmt" /* path on remote host */ diff --git a/compat/include/protocols/dumprestore.h b/compat/include/protocols/dumprestore.h index f616e31..9c6844f 100644 --- a/compat/include/protocols/dumprestore.h +++ b/compat/include/protocols/dumprestore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: dumprestore.h,v 1.19 2003/03/31 09:42:57 stelian Exp $ + * $Id: dumprestore.h,v 1.20 2003/10/26 16:05:46 stelian Exp $ */ /* @@ -71,7 +71,13 @@ #define NFS_MAGIC (int)60012 #define CHECKSUM (int)84446 +#ifdef __linux__ typedef u_int32_t dump_ino_t; +#endif + +#ifdef sunos +typedef unsigned int dump_ino_t; +#endif union u_data { char s_addrs[TP_NINDIR]; /* 1 => data; 0 => hole in inode */ @@ -91,8 +97,12 @@ union u_spcl { int32_t c_checksum; /* record checksum */ #ifdef __linux__ struct new_bsd_inode c_dinode; +#else +#ifdef sunos + struct new_bsd_inode c_dinode; #else struct dinode c_dinode; /* ownership and mode of inode */ +#endif #endif int32_t c_count; /* number of valid c_addr entries */ union u_data c_data; /* see above */ @@ -104,7 +114,8 @@ union u_spcl { int32_t c_flags; /* additional information */ int32_t c_firstrec; /* first record on volume */ int32_t c_ntrec; /* blocksize on volume */ - int32_t c_spare[31]; /* reserved for future uses */ + int32_t c_extattributes; /* additional inode info */ + int32_t c_spare[30]; /* reserved for future uses */ } s_spcl; } u_spcl; #define spcl u_spcl.s_spcl @@ -130,6 +141,15 @@ union u_spcl { #define DR_METAONLY 0x0100 /* only the metadata of the inode has been dumped */ #define DR_INODEINFO 0x0002 /* TS_END header contains c_inos information */ +#define DR_EXTATTRIBUTES 0x8000 + +/* + * extattributes inode info + */ +#define EXT_REGULAR 0 +#define EXT_MACOSFNDRINFO 1 +#define EXT_MACOSRESFORK 2 +#define EXT_ACL 3 /* @@ -144,7 +164,11 @@ struct tapebuf { unsigned int compressed:1; unsigned int flags:3; unsigned int length:28; +#ifdef sunos + char buf; +#else char buf[0]; /* the data */ +#endif }; #endif /* !_DUMPRESTORE_H_ */ diff --git a/compat/lib/bylabel.c b/compat/lib/bylabel.c index 7f710ed..96fe918 100644 --- a/compat/lib/bylabel.c +++ b/compat/lib/bylabel.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include "bylabel.h" #define PROC_PARTITIONS "/proc/partitions" diff --git a/compat/lib/compaterr.c b/compat/lib/compaterr.c index 6cd4c5f..8ae4686 100644 --- a/compat/lib/compaterr.c +++ b/compat/lib/compaterr.c @@ -37,10 +37,11 @@ #ifndef lint static const char rcsid[] = - "$Id: compaterr.c,v 1.10 2003/03/30 15:40:35 stelian Exp $"; + "$Id: compaterr.c,v 1.11 2003/10/26 16:05:46 stelian Exp $"; #endif /* not lint */ #include +#include #include #include #include diff --git a/compat/lib/compatglob.c b/compat/lib/compatglob.c index 4a83a2f..8cf77ea 100644 --- a/compat/lib/compatglob.c +++ b/compat/lib/compatglob.c @@ -65,10 +65,11 @@ #ifndef lint static const char rcsid[] = - "$Id: compatglob.c,v 1.9 2003/03/30 15:40:35 stelian Exp $"; + "$Id: compatglob.c,v 1.10 2003/10/26 16:05:46 stelian Exp $"; #endif /* not lint */ #include +#include #ifndef HAVE_GLOB @@ -358,7 +359,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) * the password file */ if ( -#ifndef __linux__ +#if !defined(__linux__) && !defined(sunos) #ifndef __NETBSD_SYSCALLS issetugid() != 0 || #endif diff --git a/config.h.in b/config.h.in index 0faf4ca..18943d2 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,9 @@ /* Define this if you want to include Quick File Access debugging code. */ #undef DEBUG_QFA +/* Define this if you want to include Mac OSX restore compatibility. */ +#undef DUMP_MACOSX + /* Define this if you have bzlib compression library. */ #undef HAVE_BZLIB diff --git a/configure b/configure index 84dac8b..5e61ddd 100755 --- a/configure +++ b/configure @@ -849,6 +849,7 @@ Optional Features: --enable-largefile enable Large File System support (default is YES) --enable-qfa enable Quick File Access support (default is YES) --enable-qfadebug include Quick File Access debugging code (default is NO) + --enable-macosx include Mac OSX restore compatibility (default is NO) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3508,6 +3509,27 @@ else fi; +# Check whether --enable-macosx or --disable-macosx was given. +if test "${enable_macosx+set}" = set; then + enableval="$enable_macosx" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define DUMP_MACOSX 1 +_ACEOF + + echo "Including Mac OSX restore compatibility code" +else + echo "Not including Mac OSX restore compatibility code" +fi + +else + echo "Not including Mac OSX restore compatibility code by default" + +fi; + + # Check whether --with-cc or --without-cc was given. if test "${with_cc+set}" = set; then diff --git a/configure.in b/configure.in index 4bc4abd..94aedbf 100644 --- a/configure.in +++ b/configure.in @@ -220,6 +220,23 @@ fi echo "Not including Quick File Access debugging code by default" ) +dnl +dnl Handle --enable-macosx +dnl +AC_ARG_ENABLE([macosx], +[ --enable-macosx include Mac OSX restore compatibility (default is NO)], +if test "$enableval" = "yes" +then + AC_DEFINE([DUMP_MACOSX],1,[Define this if you want to include Mac OSX restore compatibility.]) + echo "Including Mac OSX restore compatibility code" +else + echo "Not including Mac OSX restore compatibility code" +fi +, +echo "Not including Mac OSX restore compatibility code by default" +) + + dnl dnl set $(CC) from --with-cc=value dnl diff --git a/dump/dump.h b/dump/dump.h index 1c3c425..5b052c8 100644 --- a/dump/dump.h +++ b/dump/dump.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: dump.h,v 1.46 2003/05/12 14:16:39 stelian Exp $ + * $Id: dump.h,v 1.47 2003/10/26 16:05:46 stelian Exp $ */ /*- @@ -263,6 +263,15 @@ extern int errno; int dump_fs_open(const char *disk, ext2_filsys *fs); #endif +#ifndef __linux__ +#ifndef _PATH_UTMP +#define _PATH_UTMP "/etc/utmp" +#endif +#ifndef _PATH_FSTAB +#define _PATH_FSTAB "/etc/fstab" +#endif +#endif + #ifdef sunos extern char *calloc(); extern char *malloc(); diff --git a/dump/itime.c b/dump/itime.c index 6f59a85..7187d00 100644 --- a/dump/itime.c +++ b/dump/itime.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: itime.c,v 1.25 2003/03/30 15:40:36 stelian Exp $"; + "$Id: itime.c,v 1.26 2003/10/26 16:05:47 stelian Exp $"; #endif /* not lint */ #include @@ -52,7 +52,6 @@ static const char rcsid[] = #include #include #include -#include #ifdef __linux__ #ifdef HAVE_EXT2FS_EXT2_FS_H #include diff --git a/dump/main.c b/dump/main.c index 007a37d..1bb5ca3 100644 --- a/dump/main.c +++ b/dump/main.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.86 2003/05/12 14:16:39 stelian Exp $"; + "$Id: main.c,v 1.87 2003/10/26 16:05:47 stelian Exp $"; #endif /* not lint */ #include @@ -45,6 +45,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ static const char rcsid[] = #include #include #include +#include /* for definition of BLKFLSBUF */ #elif defined sunos #include @@ -85,6 +87,8 @@ static const char rcsid[] = #define SBOFF (SBLOCK * DEV_BSIZE) #endif +int abortifconnerr = 1; /* set to 1 if lib dumprmt.o should exit on connection errors + otherwise just print a message using msg */ /* * Dump maps used to describe what is to be dumped. */ @@ -174,6 +178,8 @@ int compressed = 0; /* use zlib to compress the output, compress level 1-9 */ long long bytes_written = 0; /* total bytes written */ long uncomprblks = 0;/* uncompressed blocks written */ +long smtc_errno; + #ifdef __linux__ char *__progname; #endif @@ -496,24 +502,36 @@ main(int argc, char *argv[]) tsize = cartridge ? 1700L*120L : 2300L*120L; } - if (strchr(tapeprefix, ':')) { - host = tapeprefix; - tapeprefix = strchr(host, ':'); - *tapeprefix++ = '\0'; + { + int i; + char *n; + + if ((n = strchr(tapeprefix, ':'))) { + for (i = 0; i < (n - tapeprefix); i++) { + if (tapeprefix[i] == '/') + break; + } + if (tapeprefix[i] != '/') { + host = tapeprefix; + tapeprefix = strchr(host, ':'); + *tapeprefix++ = '\0'; #ifdef RDUMP - if (index(tapeprefix, '\n')) { - msg("invalid characters in tape\n"); - msg("The ENTIRE dump is aborted.\n"); - exit(X_STARTUP); - } - if (rmthost(host) == 0) - exit(X_STARTUP); + if (index(tapeprefix, '\n')) { + msg("invalid characters in tape\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + if (rmthost(host) == 0) + exit(X_STARTUP); #else - msg("remote dump not enabled\n"); - msg("The ENTIRE dump is aborted.\n"); - exit(X_STARTUP); + msg("remote dump not enabled\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); #endif + } + } } + (void)setuid(getuid()); /* rmthost() is the only reason to be setuid */ if (Apath && (Afile = open(Apath, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | @@ -688,7 +706,7 @@ main(int argc, char *argv[]) exit(X_STARTUP); } #ifdef BLKFLSBUF - (void)ioctl(diskfd, BLKFLSBUF); + (void)ioctl(diskfd, BLKFLSBUF, 0); #endif retval = dump_fs_open(disk, &fs); if (retval) { diff --git a/dump/tape.c b/dump/tape.c index 1990be9..a8affbb 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.77 2003/04/18 07:47:57 stelian Exp $"; + "$Id: tape.c,v 1.78 2003/10/26 16:05:47 stelian Exp $"; #endif /* not lint */ #include @@ -60,6 +60,7 @@ int write(), read(); #ifdef __linux__ #include #include +#include /* for definition of BLKFLSBUF */ #include #endif #include @@ -110,6 +111,7 @@ extern int ntrec; /* blocking factor on tape */ extern int cartridge; char *nexttape; extern pid_t rshpid; +int eot_code = 1; long long tapea_bytes = 0; /* bytes_written at start of current volume */ static int magtapeout; /* output is really a tape */ @@ -126,7 +128,8 @@ static void killall __P((void)); static void rollforward __P((void)); #ifdef USE_QFA static int GetTapePos __P((long long *)); -static void MkTapeString __P((struct s_spcl *, long long)); +static int MkTapeString __P((struct s_spcl *, long long)); +#define FILESQFAPOS 20 #endif /* @@ -1096,6 +1099,9 @@ doslave(int cmd, long long curtapepos; union u_spcl *uspclptr; struct s_spcl *spclptr; + /* long maxntrecs = 300000000 / (ntrec * 1024); last tested: 50 000 000 */ + long maxntrecs = 50000; /* every 50MB */ + long cntntrecs = maxntrecs; #endif /* USE_QFA */ sigset_t set; @@ -1112,7 +1118,7 @@ doslave(int cmd, quit("slave couldn't reopen disk: %s\n", strerror(errno)); #ifdef __linux__ #ifdef BLKFLSBUF - (void)ioctl(diskfd, BLKFLSBUF); + (void)ioctl(diskfd, BLKFLSBUF, 0); #endif ext2fs_close(fs); retval = dump_fs_open(disk, &fs); @@ -1277,23 +1283,30 @@ doslave(int cmd, #ifdef USE_QFA if (gTapeposfd >= 0) { int i; - int firstpass = 1; - for (i = 0; i < ntrec; ++i) { + int foundone = 0; + + for (i = 0; (i < ntrec) && !foundone; ++i) { uspclptr = (union u_spcl *)&slp->tblock[i]; spclptr = &uspclptr->s_spcl; if ((spclptr->c_magic == NFS_MAGIC) && - (spclptr->c_type == TS_INODE) && - ((spclptr->c_dinode.di_mode & S_IFMT) != IFDIR) && - (spclptr->c_date == gThisDumpDate)) { - /* if an error occured previously don't - * try again */ - if (firstpass) { - firstpass = 0; + (spclptr->c_type == TS_INODE) && + (spclptr->c_date == gThisDumpDate) && + !(spclptr->c_dinode.di_mode & S_IFDIR) + ) { + foundone = 1; + /* if (cntntrecs >= maxntrecs) { only write every maxntrecs amount of data */ + cntntrecs = 0; if (gtperr == 0) gtperr = GetTapePos(&curtapepos); - } - if (gtperr == 0) - MkTapeString(spclptr, curtapepos); + /* if an error occured previously don't + * try again */ + if (gtperr == 0) { +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %ld\n", spclptr->c_inumber, curtapepos); +#endif + gtperr = MkTapeString(spclptr, curtapepos); + } + /* } */ } } } @@ -1350,6 +1363,11 @@ doslave(int cmd, * Signal the next slave to go. */ (void) kill(nextslave, SIGUSR2); +#ifdef USE_QFA + if (gTapeposfd >= 0) { + cntntrecs += ntrec; + } +#endif /* USE_QFA */ } if (nread != 0) quit("error reading command pipe: %s\n", strerror(errno)); @@ -1386,11 +1404,31 @@ dump_atomic_write(int fd, const void *buf, size_t count) while ((got = write(fd, buf, need)) > 0 && (need -= got) > 0) (char *)buf += got; } while (got == -1 && errno == EINTR); - return (got < 0 ? got : (ssize_t)count - need); + return (got < 0 ? got : count - need); } +/* +int +SetLogicalPos(void) +{ + int err = 0; + struct mt_pos buf; + + buf.mt_op = MTSETDRVBUFFER; + buf.mt_count = MT_ST_BOOLEANS | MT_ST_SCSI2LOGICAL; + if (ioctl(tapefd, MTIOCTOP, &buf) == -1) { + err = errno; + msg("[%ld] error: %d (setting logical)\n", + (unsigned long)getpid(), err); + } + return err; +} +*/ + #ifdef USE_QFA +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 /* * read the current tape position */ @@ -1401,7 +1439,7 @@ GetTapePos(long long *pos) #ifdef RDUMP if (host) { - *pos = (long long) rmtseek(0, SEEK_CUR); + *pos = (long long) rmtseek((OFF_T)0, (int)LSEEK_GET_TAPEPOS); err = *pos < 0; } else @@ -1427,8 +1465,10 @@ GetTapePos(long long *pos) return err; } -static void -MkTapeString(struct s_spcl *spclptr, long long curtapepos) { +static int +MkTapeString(struct s_spcl *spclptr, long long curtapepos) +{ + int err = 0; #ifdef DEBUG_QFA msg("inode %ld at tapepos %lld\n", spclptr->c_inumber, curtapepos); @@ -1440,7 +1480,9 @@ MkTapeString(struct s_spcl *spclptr, long long curtapepos) { curtapepos); gTps[sizeof(gTps) - 1] = '\0'; if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) { - warn("error writing tapepos file.\n"); + err = errno; + warn("error writing tapepos file. (error %d)\n", errno); } + return err; } #endif /* USE_QFA */ diff --git a/dump/traverse.c b/dump/traverse.c index 3886b47..2142abc 100644 --- a/dump/traverse.c +++ b/dump/traverse.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: traverse.c,v 1.55 2003/03/30 15:40:37 stelian Exp $"; + "$Id: traverse.c,v 1.56 2003/10/26 16:05:47 stelian Exp $"; #endif /* not lint */ #include @@ -1238,7 +1238,7 @@ dumpmap(char *map, int type, dump_ino_t ino) writerec(cp, 0); } -#if defined __linux__ && !defined(int32_t) +#if defined(__linux__) && !defined(int32_t) #define int32_t __s32 #endif @@ -1311,7 +1311,7 @@ getino(dump_ino_t inum) /* * Read a chunk of data from the disk. * Try to recover from hard errors by reading in sector sized pieces. - * Error recovery is attempted at most breademax times before seeking + * Error recovery is attempted at most BREADEMAX times before seeking * consent from the operator to continue. */ int breaderrors = 0; diff --git a/restore/dirs.c b/restore/dirs.c index dc45e7c..2392488 100644 --- a/restore/dirs.c +++ b/restore/dirs.c @@ -42,10 +42,11 @@ #ifndef lint static const char rcsid[] = - "$Id: dirs.c,v 1.23 2003/03/30 15:40:38 stelian Exp $"; + "$Id: dirs.c,v 1.24 2003/10/26 16:05:47 stelian Exp $"; #endif /* not lint */ #include +#include #include #include #include @@ -58,8 +59,13 @@ static const char rcsid[] = #endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include #include +#endif #endif /* __linux__ */ #include @@ -73,8 +79,12 @@ static const char rcsid[] = #ifdef __linux__ #include #else +#ifdef sunos +#include +#else #include #endif +#endif #include "pathnames.h" #include "restore.h" @@ -151,6 +161,10 @@ static void rst_seekdir __P((RST_DIR *, long, long)); static long rst_telldir __P((RST_DIR *)); static struct direct *searchdir __P((dump_ino_t, char *)); +#ifdef sunos +extern int fdsmtc; +#endif + /* * Extract directory contents, building up a directory structure * on disk for extraction by name. @@ -659,8 +673,11 @@ setdirmodes(int flags) if (node.flags) #ifdef __linux__ (void) fsetflags(cp, node.flags); +#else +#ifdef sunos #else (void) chflags(cp, node.flags); +#endif #endif utimes(cp, node.timep); ep->e_flags &= ~NEW; @@ -727,7 +744,7 @@ inodetype(dump_ino_t ino) * If requested, save its pertinent mode, owner, and time info. */ static struct inotab * -#ifdef __linux__ +#if defined(__linux__) || defined(sunos) allocinotab(dump_ino_t ino, struct new_bsd_inode *dip, long seekpt) #else allocinotab(dump_ino_t ino, struct dinode *dip, long seekpt) @@ -746,17 +763,17 @@ allocinotab(dump_ino_t ino, struct dinode *dip, long seekpt) if (mf == NULL) return (itp); node.ino = ino; -#ifdef __linux__ +#if defined(__linux__) || defined(sunos) node.timep[0].tv_sec = dip->di_atime.tv_sec; node.timep[0].tv_usec = dip->di_atime.tv_usec; node.timep[1].tv_sec = dip->di_mtime.tv_sec; node.timep[1].tv_usec = dip->di_mtime.tv_usec; -#else /* __linux__ */ +#else /* __linux__ || sunos */ node.timep[0].tv_sec = dip->di_atime; node.timep[0].tv_usec = dip->di_atimensec / 1000; node.timep[1].tv_sec = dip->di_mtime; node.timep[1].tv_usec = dip->di_mtimensec / 1000; -#endif /* __linux__ */ +#endif /* __linux__ || sunos */ node.mode = dip->di_mode; node.flags = dip->di_flags; node.uid = dip->di_uid; diff --git a/restore/extern.h b/restore/extern.h index bf81109..e2702ed 100644 --- a/restore/extern.h +++ b/restore/extern.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: extern.h,v 1.22 2003/03/30 15:40:38 stelian Exp $ + * $Id: extern.h,v 1.23 2003/10/26 16:05:48 stelian Exp $ */ /*- @@ -39,6 +39,12 @@ #include #include +#ifndef __P +#include +#endif +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif struct entry *addentry __P((char *, dump_ino_t, int)); long addfile __P((char *, dump_ino_t, int)); @@ -131,5 +137,20 @@ int GetTapePos __P((long long *)); int GotoTapePos __P((long long)); void ReReadFromTape __P((void)); void ReReadInodeFromTape __P((dump_ino_t)); +void GetPathFile __P((char *, char *, char *)); + +#ifdef sunos +int GetSCSIIDFromPath __P((char *, long *)); +int OpenSMTCmt(char *); +#endif #endif void RequestVol __P((long)); + +#ifdef DUMP_MACOSX +int extractfinderinfoufs __P((char *)); +int extractresourceufs __P((char *)); +int CreateAppleDoubleFileRes __P((char *, FndrFileInfo *, mode_t, int, struct timeval *, u_int32_t, u_int32_t)); +#endif + + + diff --git a/restore/interactive.c b/restore/interactive.c index 51cacb4..ecbffda 100644 --- a/restore/interactive.c +++ b/restore/interactive.c @@ -37,10 +37,11 @@ #ifndef lint static const char rcsid[] = - "$Id: interactive.c,v 1.26 2003/03/30 15:40:38 stelian Exp $"; + "$Id: interactive.c,v 1.27 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ #include +#include #include #include @@ -52,8 +53,13 @@ static const char rcsid[] = #endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include #include +#endif #endif /* __linux__ */ #include @@ -67,6 +73,9 @@ static const char rcsid[] = #ifdef __linux__ #include +#endif + +#if defined(__linux__) || defined(sunos) extern char * __progname; #endif diff --git a/restore/main.c b/restore/main.c index 98674e4..77b9d7d 100644 --- a/restore/main.c +++ b/restore/main.c @@ -37,11 +37,12 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.44 2003/03/30 15:40:38 stelian Exp $"; + "$Id: main.c,v 1.45 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ #include #include +#include #include #include #include @@ -59,7 +60,15 @@ static const char rcsid[] = #include #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#include +#include +#include +#else #include +#endif #endif /* __linux__ */ #include @@ -77,6 +86,9 @@ static const char rcsid[] = #include "restore.h" #include "extern.h" +int abortifconnerr = 1; /* set to 1 if lib dumprmt.o should exit on connection errors + otherwise just print a message using msg */ + int aflag = 0, bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; int hflag = 1, mflag = 1, Mflag = 0, Nflag = 0, Vflag = 0, zflag = 0; int uflag = 0, lflag = 0, Lflag = 0, oflag = 0; @@ -112,6 +124,8 @@ unsigned long qfadumpdate; long long curtapepos; #endif /* USE_QFA */ +long smtc_errno; + #if defined(__linux__) || defined(sunos) char *__progname; #endif @@ -379,6 +393,18 @@ main(int argc, char *argv[]) /* end reading header info */ /* tape position table starts here */ gSeekstart = ftell(gTapeposfp); /* remember for later use */ +#ifdef sunos + if (GetSCSIIDFromPath(inputdev, &scsiid)) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + if (scsiid < 0) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + errx(1, "can't open smtc device: %s, %d\n", smtcpath, errno); + } +#endif } #endif /* USE_QFA */ @@ -535,6 +561,11 @@ main(int argc, char *argv[]) setdirmodes(oflag ? FORCE : 0); if (dflag) checkrestore(); +#ifdef sunos + if (fdsmtc != -1) { + close(fdsmtc); + } +#endif /* sunos */ #ifdef DEBUG_QFA tiend = time(NULL); titaken = tiend - tistart; @@ -547,6 +578,18 @@ main(int argc, char *argv[]) #ifdef DEBUG_QFA tistart = time(NULL); #endif +#ifdef sunos + if (GetSCSIIDFromPath(inputdev, &scsiid)) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + if (scsiid < 0) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + errx(1, "can't open smtc device: %s, %d\n", smtcpath, errno); + } +#endif /* sunos */ setup(); msg("writing QFA positions to %s\n", gTapeposfile); (void) umask(orig_umask); @@ -556,7 +599,7 @@ main(int argc, char *argv[]) errx(1, "can't create tapeposfile\n"); (void) umask(FORCED_UMASK); /* print QFA-file header */ - sprintf(gTps, "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION,(unsigned long)spcl.c_date); + sprintf(gTps, "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) errx(1, "can't write tapeposfile\n"); sprintf(gTps, "ino\ttapeno\ttapepos\n"); @@ -578,14 +621,19 @@ main(int argc, char *argv[]) treescan(name, ino, addfile); } createfiles(); +#ifdef sunos + if (fdsmtc != -1) { + close(fdsmtc); + } +#endif /* sunos */ #ifdef DEBUG_QFA tiend = time(NULL); titaken = tiend - tistart; - msg("writing QFA positions took %d:%02d:%02d\n", titaken / 3600, + msg("writing QFA positions took %d:%02d:%02d\n", titaken / 3600, (titaken % 3600) / 60, titaken % 60); #endif /* DEBUG_QFA */ break; -#endif /* USE_QFA */ +#endif /* USE_QFA */ } exit(0); /* NOTREACHED */ diff --git a/restore/restore.c b/restore/restore.c index 5ac6c87..9d18c6b 100644 --- a/restore/restore.c +++ b/restore/restore.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: restore.c,v 1.31 2003/03/30 15:40:39 stelian Exp $"; + "$Id: restore.c,v 1.32 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ #include @@ -54,8 +54,14 @@ static const char rcsid[] = #endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include +#endif #endif /* __linux__ */ + #include #include @@ -213,8 +219,11 @@ removeoldleaves(void) continue; #ifdef __linux__ (void)fprintf(stderr, "BUG! Should call delwhiteout\n"); +#else +#ifdef sunos #else delwhiteout(ep); +#endif #endif freeentry(ep); } @@ -799,12 +808,42 @@ createleaves(char *symtabfile) doremove = 0; (void) extractfile(ep, doremove); ep->e_flags &= ~(NEW|EXTRACT); + +finderres: + if ((first == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: +#ifdef DUMP_MACOSX + (void)extractfinderinfoufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); +#endif + break; + case EXT_MACOSRESFORK: +#ifdef DUMP_MACOSX + (void)extractresourceufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); +#endif + break; + case EXT_ACL: + msg("ACLs not supported in this version, skipping\n"); + skipfile(); + break; + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + goto finderres; + } + /* * We checkpoint the restore after every tape reel, so * as to simplify the amount of work required by the * 'R' command. */ - next: +next: if (curvol != volno) { dumpsymtable(symtabfile, volno); skipmaps(); @@ -844,8 +883,9 @@ createfiles(void) long curvol; #ifdef USE_QFA long tnum, tmpcnt; - long long tpos, curtpos; + long long tpos, curtpos = 0; time_t tistart, tiend, titaken; + int volChg; #endif Vprintf(stdout, "Extract requested files\n"); @@ -907,38 +947,41 @@ createfiles(void) #ifdef USE_QFA tistart = time(NULL); if (tapeposflag) { - /* get tape position for inode (position directly) */ - (void)Inode2Tapepos(next, &tnum, &tpos, 1); - if (tpos == 0) - /* get tape position for last available inode - * (position before) */ - (void)Inode2Tapepos(next, &tnum, &tpos, 0); + /* get tape position for inode */ + (void)Inode2Tapepos(next, &tnum, &tpos, 0); if (tpos != 0) { - if (tnum != volno) + if (tnum != volno) { (void)RequestVol(tnum); + volChg = 1; + } else { + volChg = 0; + } if (GetTapePos(&curtpos) == 0) { /* curtpos +1000 ???, some drives * might be too slow */ - if (tpos != curtpos) { + if (((tpos > (curtpos + 1000)) && (volChg == 0)) || ((tpos != curtpos) && (volChg == 1))) { + volChg = 0; #ifdef DEBUG_QFA - msg("positioning tape %ld from %lld to %lld for inode %10lu ...\n", volno, curtpos, tpos, (unsigned long)next); + msg("positioning tape %ld from %lld to %lld for inode %lu ...\n", volno, curtpos, tpos, (unsigned long)next); #endif if (GotoTapePos(tpos) == 0) { #ifdef DEBUG_QFA - if (GetTapePos(&curtpos) == 0) - msg("before resync at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + if (GetTapePos(&curtpos) == 0) { + msg("before resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } #endif ReReadInodeFromTape(next); #ifdef DEBUG_QFA - if (GetTapePos(&curtpos) == 0) - msg("after resync at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + if (GetTapePos(&curtpos) == 0) { + msg("after resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } #endif } - } + } else { #ifdef DEBUG_QFA - else - msg("already at tape %ld position %ld for inode %10lu ...\n", volno, tpos, (unsigned long)next); + msg("already at tape %ld position %ld for inode %lu ...\n", volno, tpos, (unsigned long)next); #endif + } } } } @@ -999,9 +1042,9 @@ createfiles(void) panic("corrupted symbol table\n"); #ifdef USE_QFA if (!createtapeposflag) +#endif fprintf(stderr, "%s: (inode %lu) not found on tape\n", myname(ep), (unsigned long)next); -#endif ep->e_flags &= ~NEW; next = lowerbnd(next); } @@ -1020,13 +1063,41 @@ createfiles(void) #endif sprintf(gTps, "%ld\t%ld\t%lld\n", (unsigned long)curfile.ino, volno, curtapepos); if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) - warn("error writing tapepos file.\n"); + warn("error writing tapepos file.\n"); skipfile(); - } - else { - msg("restoring %s\n", myname(ep)); + } else { #endif /* USE_QFA */ (void) extractfile(ep, 0); + +finderres: + if ((next == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: +#ifdef DUMP_MACOSX + (void)extractfinderinfoufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); +#endif + break; + case EXT_MACOSRESFORK: +#ifdef DUMP_MACOSX + (void)extractresourceufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); +#endif + break; + case EXT_ACL: + msg("ACLs not supported in this version, skipping\n"); + skipfile(); + break; + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + goto finderres; + } + #ifdef USE_QFA } #endif /* USE_QFA */ @@ -1054,8 +1125,11 @@ createlinks(void) continue; #ifdef __linux__ (void)fprintf(stderr, "BUG! Should call addwhiteout\n"); +#else +#ifdef sunos #else (void) addwhiteout(myname(ep)); +#endif #endif ep->e_flags &= ~NEW; } diff --git a/restore/restore.h b/restore/restore.h index 0dea9ca..9239b07 100644 --- a/restore/restore.h +++ b/restore/restore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000-2002 * - * $Id: restore.h,v 1.27 2003/03/30 15:40:40 stelian Exp $ + * $Id: restore.h,v 1.28 2003/10/26 16:05:48 stelian Exp $ */ /* @@ -180,6 +180,11 @@ extern int gTapeposfd; extern int createtapeposflag; extern unsigned long qfadumpdate; extern long long curtapepos; +#ifdef sunos +int fdsmtc; +long scsiid; +char smtcpath[2048]; +#endif #endif /* USE_QFA */ #define do_compare_error \ diff --git a/restore/symtab.c b/restore/symtab.c index 5bd5e67..3e6d3fc 100644 --- a/restore/symtab.c +++ b/restore/symtab.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: symtab.c,v 1.21 2003/03/30 15:40:40 stelian Exp $"; + "$Id: symtab.c,v 1.22 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ /* @@ -63,7 +63,12 @@ static const char rcsid[] = #endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include +#endif #endif /* __linux__ */ #include diff --git a/restore/tape.c b/restore/tape.c index 553abbc..b4fa15d 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -42,11 +42,12 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.74 2003/03/31 09:42:59 stelian Exp $"; + "$Id: tape.c,v 1.75 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ #include #include +#include #include #include #include @@ -72,8 +73,18 @@ static const char rcsid[] = #include #include #else /* __linux__ */ +#ifdef sunos +#define quad_t int64_t +#include +#include +#include +#else #include +#endif #endif /* __linux__ */ +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif #include #ifdef HAVE_ZLIB @@ -138,6 +149,10 @@ static int converthead __P((struct s_spcl *)); static void converttapebuf __P((struct tapebuf *)); static void readtape __P((char *)); static void setdumpnum __P((void)); +#ifdef DUMP_MACOSX +static void xtrfilefinderinfo __P((char *, size_t)); +#endif + static u_int swabi __P((u_int)); #if 0 static u_long swabl __P((u_long)); @@ -179,12 +194,19 @@ static void xtrcmpskip __P((char *, size_t)); static int readmapflag; static int readingmaps; /* set to 1 while reading the maps */ +#ifdef DUMP_MACOSX +static DumpFinderInfo gFndrInfo; +#endif + /* * Set up an input source. This is called from main.c before setup() is. */ void setinput(char *source) { + int i; + char *n; + FLUSHTAPEBUF(); if (bflag) newtapebuf(ntrec); @@ -193,12 +215,18 @@ setinput(char *source) terminal = stdin; #ifdef RRESTORE - if (strchr(source, ':')) { - host = source; - source = strchr(host, ':'); - *source++ = '\0'; - if (rmthost(host) == 0) - exit(1); + if ((n = strchr(source, ':'))) { + for (i = 0; i < (n - source); i++) { + if (source[i] == '/') + break; + } + if (source[i] != '/') { + host = source; + source = strchr(host, ':'); + *source++ = '\0'; + if (rmthost(host) == 0) + exit(1); + } } else #endif if (strcmp(source, "-") == 0) { @@ -504,7 +532,7 @@ again: goto again; } } -#endif +#endif /* USE_QFA */ return; } closemt(); @@ -529,9 +557,17 @@ again: } if (haderror || (bot_code && !Mflag)) { haderror = 0; +#ifdef sunos fprintf(stderr, "Mount volume %ld\n", (long)newvol); - fprintf(stderr, "Enter ``none'' if there are no more volumes\n"); - fprintf(stderr, "otherwise enter volume name (default: %s) ", magtape); +#else + fprintf(stderr, "Mount tape volume %ld\n", (long)newvol); +#endif + fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); +#ifdef sunos + fprintf(stderr, "then enter volume name (default: %s) ", magtape); +#else + fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); +#endif (void) fflush(stderr); (void) fgets(buf, TP_BSIZE, terminal); if (feof(terminal)) @@ -548,6 +584,15 @@ again: magtape[pos - magtape] = '\0'; } } +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) { + if (OpenSMTCmt(magtape) < 0) { + volno = -1; + haderror = 1; + goto again; + } + } +#endif /* USE_QFA */ #ifdef RRESTORE if (host) mt = rmtopen(magtape, O_RDONLY); @@ -589,7 +634,11 @@ gethdr: } if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { fprintf(stderr, "Wrong dump date\n\tgot: %s", +#ifdef sunos + ctime(&tmpbuf.c_date)); +#else ctime4(&tmpbuf.c_date)); +#endif fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; haderror = 1; @@ -686,17 +735,33 @@ setdumpnum(void) tcom.mt_op = MTFSF; tcom.mt_count = dumpnum - 1; #ifdef RRESTORE - if (host) - rmtioctl(MTFSF, dumpnum - 1); - else + if (host) { + if (rmtioctl(MTFSF, dumpnum - 1) < 0) { + fprintf(stderr, "rmtioctl MTFSF: %s\n", strerror(errno)); + exit(1); + } + } else #endif - if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) - warn("ioctl MTFSF"); + if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) { + fprintf(stderr, "rmtioctl MTFSF: %s\n", strerror(errno)); + exit(1); + /* warn("ioctl MTFSF"); */ + } } void printdumpinfo(void) { +#ifdef sunos + Vprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); + Vprintf(stdout, "Dumped from: %s", + (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate)); + if (spcl.c_host[0] == '\0') + return; + Vprintf(stdout, "Level %d dump of %s on %s:%s\n", + spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); + Vprintf(stdout, "Label: %s\n", spcl.c_label); +#else fprintf(stdout, "Dump date: %s", ctime4(&spcl.c_date)); fprintf(stdout, "Dumped from: %s", (spcl.c_ddate == 0) ? "the epoch\n" : ctime4(&spcl.c_ddate)); @@ -705,6 +770,7 @@ printdumpinfo(void) fprintf(stdout, "Level %d dump of %s on %s:%s\n", spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); fprintf(stdout, "Label: %s\n", spcl.c_label); +#endif } void @@ -719,12 +785,6 @@ printvolinfo(void) } } -#ifdef sunos -struct timeval - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* and microseconds */ -}; -#endif int extractfile(struct entry *ep, int doremove) @@ -830,8 +890,15 @@ extractfile(struct entry *ep, int doremove) if (flags) #ifdef __linux__ (void) fsetflags(name, flags); +#else +#ifdef sunos + { + warn("%s: cannot call chflags", name); + /* (void) chflags(name, flags); */ + } #else (void) chflags(name, flags); +#endif #endif skipfile(); utimes(name, timep); @@ -862,7 +929,17 @@ extractfile(struct entry *ep, int doremove) (void) fsetflags(name, flags); } #else +#ifdef sunos + { + warn("%s: cannot call chflags on a special file", name); + /* (void) chflags(name, flags); */ + } +#else + { + warn("%s: chflags called on a special file", name); (void) chflags(name, flags); + } +#endif #endif skipfile(); utimes(name, timep); @@ -897,8 +974,15 @@ extractfile(struct entry *ep, int doremove) if (flags) #ifdef __linux__ (void) fsetflags(name, flags); +#else +#ifdef sunos + { + warn("%s: cannot call chflags", name); + /* (void) chflags(name, flags); */ + } #else (void) chflags(name, flags); +#endif #endif utimes(name, timep); return (GOOD); @@ -907,6 +991,180 @@ extractfile(struct entry *ep, int doremove) /* NOTREACHED */ } +#ifdef DUMP_MACOSX +int +extractfinderinfoufs(char *name) +{ + int err; + char oFileRsrc[MAXPATHLEN]; + int flags; + mode_t mode; + struct timeval timep[2]; + struct entry *ep; + int sz; + attrinfo_block_t gABuf; + u_int32_t uid; + u_int32_t gid; + char path[MAXPATHLEN], fname[MAXPATHLEN]; + + curfile.name = name; + curfile.action = USING; + timep[0].tv_sec = curfile.dip->di_atime.tv_sec; + timep[0].tv_usec = curfile.dip->di_atime.tv_usec; + timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; + timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; + mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + uid = curfile.dip->di_uid; + gid = curfile.dip->di_gid; + + switch (mode & IFMT) { + + default: + fprintf(stderr, "%s: (extr. finfoufs) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFDIR: + fprintf(stderr, "%s: (extr. finfoufs[IFDIR]) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFLNK: + skipfile(); + return (GOOD); + + case IFREG: + Vprintf(stdout, "extract finderinfo file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + getfile(xtrfilefinderinfo, xtrskip); + + GetPathFile(name, path, fname); + strcpy(oFileRsrc, path); + strcat(oFileRsrc, "._"); + strcat(oFileRsrc, fname); + + if ((err = CreateAppleDoubleFileRes(oFileRsrc, &gFndrInfo.fndrinfo, + mode, flags, timep, uid, gid)) != 0) { + fprintf(stderr, "%s: cannot create finderinfo: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + return (GOOD); + } + /* NOTREACHED */ +} + + +int +extractresourceufs(char *name) +{ + char oFileRsrc[MAXPATHLEN]; + int flags; + mode_t mode; + struct timeval timep[2]; + char path[MAXPATHLEN], fname[MAXPATHLEN]; + ASDHeaderPtr hp; + ASDEntryPtr ep; + u_long loff; + u_int32_t uid; + u_int32_t gid; + u_int64_t di_size; + char *p; + char buf[1024]; + + curfile.name = name; + curfile.action = USING; + timep[0].tv_sec = curfile.dip->di_atime.tv_sec; + timep[0].tv_usec = curfile.dip->di_atime.tv_usec; + timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; + timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; + mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + uid = curfile.dip->di_uid; + gid = curfile.dip->di_gid; + di_size = curfile.dip->di_size; + + switch (mode & IFMT) { + + default: + fprintf(stderr, "%s: (extr. resufs) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFDIR: + fprintf(stderr, "%s: (extr. resufs [IFDIR]) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFLNK: + skipfile(); + return (GOOD); + + case IFREG: + Vprintf(stdout, "extract resource file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + + GetPathFile(name, path, fname); + strcpy(oFileRsrc, path); + strcat(oFileRsrc, "._"); + strcat(oFileRsrc, fname); + + if ((ofile = open(oFileRsrc, O_RDONLY, 0)) < 0) { + fprintf(stderr, "%s: cannot read finderinfo: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + read(ofile, buf, 70); + (void) close(ofile); + p = buf; + hp = (ASDHeaderPtr)p; + /* the header */ + hp->entries++; + p += sizeof(ASDHeader) - CORRECT; + ep = (ASDEntryPtr)p; + /* the finderinfo entry */ + ep->offset += sizeof(ASDEntry); + loff = ep->offset; + + p += sizeof(ASDEntry); + /* the finderinfo data */ + bcopy(p, p + sizeof(ASDEntry), INFOLEN); + ep = (ASDEntryPtr)p; + /* the new resourcefork entry */ + ep->entryID = EntryRSRCFork; + ep->offset = loff + INFOLEN; + ep->len = di_size; + /* write the new appledouble entries to the file */ + if ((ofile = open(oFileRsrc, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + fprintf(stderr, "%s: cannot create resource file: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + write(ofile, buf, 70 + sizeof(ASDEntry)); + /* and add the resource data from tape */ + getfile(xtrfile, xtrskip); + + (void) fchown(ofile, uid, gid); + (void) fchmod(ofile, mode); + (void) close(ofile); + (void) fsetflags(oFileRsrc, flags); + utimes(oFileRsrc, timep); + return (GOOD); + } + /* NOTREACHED */ +} +#endif /* DUMP_MACOSX */ + /* * skip over bit maps on the tape */ @@ -1024,6 +1282,16 @@ xtrfile(char *buf, size_t size) (unsigned long)curfile.ino, curfile.name); } +#ifdef DUMP_MACOSX +static void +xtrfilefinderinfo(char *buf, size_t size) +{ + if (Nflag) + return; + bcopy(buf, &gFndrInfo, size); +} +#endif /* DUMP_MACOSX */ + /* * Skip over a hole in a file. */ @@ -2580,7 +2848,132 @@ swabl(u_long x) } #endif +void +RequestVol(long tnum) +{ + FLUSHTAPEBUF(); + getvol(tnum); +} + #ifdef USE_QFA +#ifdef sunos +extern int fdsmtc; + +struct uscsi_cmd { + int uscsi_flags; /* read, write, etc. see below */ + short uscsi_status; /* resulting status */ + short uscsi_timeout; /* Command Timeout */ + caddr_t uscsi_cdb; /* cdb to send to target */ + caddr_t uscsi_bufaddr; /* i/o source/destination */ + u_int uscsi_buflen; /* size of i/o to take place */ + u_int uscsi_resid; /* resid from i/o operation */ + u_char uscsi_cdblen; /* # of valid cdb bytes */ + u_char uscsi_rqlen; /* size of uscsi_rqbuf */ + u_char uscsi_rqstatus; /* status of request sense cmd */ + u_char uscsi_rqresid; /* resid of request sense cmd */ + caddr_t uscsi_rqbuf; /* request sense buffer */ + void *uscsi_reserved_5; /* Reserved for Future Use */ +}; + +#define CDB_GROUP0 6 /* 6-byte cdb's */ +#define CDB_GROUP1 10 /* 10-byte cdb's */ +#define CDB_GROUP2 10 /* 10-byte cdb's */ +#define CDB_GROUP3 0 /* reserved */ +#define CDB_GROUP4 16 /* 16-byte cdb's */ +#define CDB_GROUP5 12 /* 12-byte cdb's */ +#define CDB_GROUP6 0 /* reserved */ +#define CDB_GROUP7 0 /* reserved */ + +#define USCSI_WRITE 0x00000 /* send data to device */ +#define USCSI_SILENT 0x00001 /* no error messages */ +#define USCSI_DIAGNOSE 0x00002 /* fail if any error occurs */ +#define USCSI_ISOLATE 0x00004 /* isolate from normal commands */ +#define USCSI_READ 0x00008 /* get data from device */ +#define USCSI_RESET 0x04000 /* Reset target */ +#define USCSI_RESET_ALL 0x08000 /* Reset all targets */ +#define USCSI_RQENABLE 0x10000 /* Enable Request Sense extensions */ + +#define USCSIIOC (0x04 << 8) +#define USCSICMD (USCSIIOC|201) /* user scsi command */ + +#define USCSI_TIMEOUT 30 +#define USCSI_SHORT_TIMEOUT 900 +#define USCSI_LONG_TIMEOUT 14000 + +#define B(s,i) ((unsigned char)((s) >> i)) +#define B1(s) ((unsigned char)(s)) + +#define MSB4(s,v) *(s)=B(v,24),(s)[1]=B(v,16), (s)[2]=B(v,8), (s)[3]=B1(v) + + +int +GetTapePos(long long *pos) +{ + int err = 0; + struct uscsi_cmd scmd; + char buf[512]; + char parm[512 * 8]; + long lpos; + + (void)memset((void *)buf, 0, sizeof(buf)); + (void)memset((void *)&scmd, 0, sizeof(scmd)); + scmd.uscsi_flags = USCSI_READ|USCSI_SILENT; + scmd.uscsi_timeout = USCSI_TIMEOUT; + scmd.uscsi_cdb = buf; + scmd.uscsi_cdblen = CDB_GROUP1; + buf[0] = 0x34; /* read position */ + buf[1] = 0; + (void)memset((void *)parm, 0, 512); + scmd.uscsi_bufaddr = parm; + scmd.uscsi_buflen = 56; + if (ioctl(fdsmtc, USCSICMD, &scmd) == -1) { + err = errno; + return err; + } + (void)memcpy(&lpos, &parm[4], sizeof(long)); + *pos = lpos; + return err; +} + +int +GotoTapePos(long long pos) +{ + int err = 0; + struct uscsi_cmd scmd; + char buf[512]; + char parm[512 * 8]; + long lpos = (long)pos; + + (void)memset((void *)buf, 0, sizeof(buf)); + (void)memset((void *)&scmd, 0, sizeof(scmd)); + scmd.uscsi_flags = USCSI_WRITE|USCSI_SILENT; + scmd.uscsi_timeout = 360; /* 5 Minutes */ + scmd.uscsi_cdb = buf; + scmd.uscsi_cdblen = CDB_GROUP1; + buf[0] = 0x2b; /* locate */ + buf[1] = 0; + MSB4(&buf[3], lpos); + (void)memset((void *)parm, 0, 512); + scmd.uscsi_bufaddr = NULL; + scmd.uscsi_buflen = 0; + if (ioctl(fdsmtc, USCSICMD, &scmd) == -1) { + err = errno; + return err; + } + return err; +} +#endif + +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 + +#ifdef __linux__ +typedef struct mt_pos { + short mt_op; + int mt_count; +} MTPosRec, *MTPosPtr; + + /* * get the current position of the tape */ @@ -2591,7 +2984,7 @@ GetTapePos(long long *pos) #ifdef RDUMP if (host) { - *pos = (long long) rmtseek(0, SEEK_CUR); + *pos = (long long) rmtseek((OFF_T)0, (int)LSEEK_GET_TAPEPOS); err = *pos < 0; } else @@ -2617,11 +3010,6 @@ GetTapePos(long long *pos) return err; } -typedef struct mt_pos { - short mt_op; - int mt_count; -} MTPosRec, *MTPosPtr; - /* * go to specified position on tape */ @@ -2632,7 +3020,7 @@ GotoTapePos(long long pos) #ifdef RDUMP if (host) - err = (rmtseek(pos, SEEK_SET) < 0); + err = (rmtseek((OFF_T)pos, (int)LSEEK_GO2_TAPEPOS) < 0); else #endif { @@ -2655,6 +3043,7 @@ GotoTapePos(long long pos) } return err; } +#endif /* __linux__ */ /* * read next data from tape to re-sync @@ -2676,29 +3065,42 @@ ReReadFromTape(void) void ReReadInodeFromTape(dump_ino_t theino) { - long cntloop = 0; + long cntloop = 0; FLUSHTAPEBUF(); noresyncmesg = 1; do { cntloop++; gethead(&spcl); - } while (!(spcl.c_inumber == theino && spcl.c_type == TS_INODE && spcl.c_date == dumpdate) && (cntloop < ntrec)); + } while (!(spcl.c_inumber == theino && spcl.c_type == TS_INODE && spcl.c_date == dumpdate)); #ifdef DEBUG_QFA - fprintf(stderr, "%ld reads\n", cntloop); - if (cntloop == ntrec) { - fprintf(stderr, "DEBUG: bufsize %d\n", bufsize); - fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec); - } + fprintf(stderr, "DEBUG: %ld reads\n", cntloop); + fprintf(stderr, "DEBUG: bufsize %ld\n", bufsize); + fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec); + fprintf(stderr, "DEBUG: %ld reads\n", cntloop); #endif findinode(&spcl); noresyncmesg = 0; } -#endif /* USE_QFA */ -void -RequestVol(long tnum) +#ifdef sunos +int +OpenSMTCmt(char *themagtape) { - FLUSHTAPEBUF(); - getvol(tnum); + if (GetSCSIIDFromPath(themagtape, &scsiid)) { + fprintf(stderr, "can't get SCSI-ID for %s\n", themagtape); + return -1; + } + if (scsiid < 0) { + fprintf(stderr, "can't get SCSI-ID for %s\n", themagtape); + return -1; + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + fprintf(stderr, "can't open smtc device: %s, %d\n", smtcpath, errno); + return -1; + } + return 0; } +#endif /* sunos */ +#endif /* USE_QFA */ diff --git a/restore/utilities.c b/restore/utilities.c index 838ebe7..d053938 100644 --- a/restore/utilities.c +++ b/restore/utilities.c @@ -37,10 +37,12 @@ #ifndef lint static const char rcsid[] = - "$Id: utilities.c,v 1.22 2003/03/30 15:40:40 stelian Exp $"; + "$Id: utilities.c,v 1.23 2003/10/26 16:05:48 stelian Exp $"; #endif /* not lint */ #include +#include +#include #include #include #include @@ -53,6 +55,7 @@ static const char rcsid[] = #ifdef __linux__ #include #include +#include #ifdef HAVE_EXT2FS_EXT2_FS_H #include #else @@ -61,10 +64,18 @@ static const char rcsid[] = #include #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#include +#else #include #include +#endif #endif /* __linux__ */ - +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif #include "restore.h" #include "extern.h" @@ -251,11 +262,14 @@ linkit(char *existing, char *new, int type) * Most likely, the immutable or append-only attribute * is set. Clear the attributes and try again. */ +#ifdef sunos +#else if (fgetflags (existing, &s) != -1 && fsetflags (existing, 0) != -1) { ret = link(existing, new); fsetflags(existing, s); } +#endif #endif if (ret < 0) { warn("warning: cannot create hard link %s->%s", @@ -467,6 +481,51 @@ panic(fmt, va_alist) } } +void resizemaps(dump_ino_t oldmax, dump_ino_t newmax) +{ + char *map; + + if (usedinomap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for active inode map"); + memcpy(map, usedinomap, howmany(oldmax, NBBY)); + free(usedinomap); + usedinomap = map; + } + if (dumpmap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for file dump list"); + memcpy(map, dumpmap, howmany(oldmax, NBBY)); + free(dumpmap); + dumpmap = map; + } +} + +void +GetPathFile(char *source, char *path, char *fname) +{ + char *p, *s; + + *path = 0; + *fname = 0; + p = s = source; + while (*s) { + if (*s == '/') { + p = s + 1; + } + s++; + } + if (p == source) { + *path = 0; + } else { + strncpy(path, source, p - source); + path[p - source] = 0; + } + strcpy(fname, p); +} + #ifdef USE_QFA /* * search for ino in QFA file @@ -493,7 +552,11 @@ Inode2Tapepos(dump_ino_t ino, long *tnum, long long *tpos, int exactmatch) *tnum = 0; if (fseek(gTapeposfp, gSeekstart, SEEK_SET) == -1) return errno; - while (fgets(gTps, sizeof(gTps), gTapeposfp) != NULL) { + while (1) { + gSeekstart = ftell(gTapeposfp); /* remember for later use */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) { + return 0; + } gTps[strlen(gTps) - 1] = 0; /* delete end of line */ p = gTps; bzero(numbuff, sizeof(numbuff)); @@ -538,26 +601,123 @@ Inode2Tapepos(dump_ino_t ino, long *tnum, long long *tpos, int exactmatch) } return 0; } + +#ifdef sunos +int +GetSCSIIDFromPath(char *devPath, long *id) +{ + int len; + char fbuff[2048]; + char path[2048]; + char fname[2048]; + char *fpn = fname; + char idstr[32]; + char *ip = idstr; + + bzero(fbuff, sizeof(fbuff)); + if ((len = readlink(devPath, fbuff, 2048)) == -1) { + return errno; + } + fbuff[len] = 0; + GetPathFile(fbuff, path, fname); + (void)memset(idstr, 0, sizeof(idstr)); + while (*fpn && (*fpn != ',')) { + if (*fpn <= '9' && *fpn >= '0') { + *ip = *fpn; + ip++; + } + fpn++; + } + if (*idstr) { + *id = atol(idstr); + } else { + *id = -1; + } + return 0; +} +#endif #endif /* USE_QFA */ -void resizemaps(dump_ino_t oldmax, dump_ino_t newmax) +#ifdef DUMP_MACOSX +int +CreateAppleDoubleFileRes(char *oFile, FndrFileInfo *finderinfo, mode_t mode, int flags, + struct timeval *timep, u_int32_t uid, u_int32_t gid) { - char *map; + int err = 0; + int fdout; + char *p; + char *f; + char *pp; + ASDHeaderPtr hp; + ASDEntryPtr ep; + long thesize; + long n; + long loops; + long remain; + + + n = 1; /* number of entries in double file ._ only finderinfo */ + /* + no data fork + n++; + currently no resource fork + n++; + */ + + thesize = sizeof(ASDHeader) + (n * sizeof(ASDEntry)) + INFOLEN; + if ((pp = p = (char *)malloc(thesize)) == NULL) { + err = errno; + return err; + } - if (usedinomap) { - map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); - if (map == NULL) - errx(1, "no memory for active inode map"); - memcpy(map, usedinomap, howmany(oldmax, NBBY)); - free(usedinomap); - usedinomap = map; + hp = (ASDHeaderPtr)p; + p += sizeof(ASDHeader); + ep = (ASDEntryPtr)p; + p += sizeof(ASDEntry) * n; + + hp->magic = ADOUBLE_MAGIC; + hp->version = ASD_VERSION2; + + bzero(&hp->filler, sizeof(hp->filler)); + hp->entries = (short)n; + + ep->entryID = EntryFinderInfo; + ep->offset = p - pp - CORRECT; + ep->len = INFOLEN; /* sizeof(MacFInfo) + sizeof(FXInfo); */ + bzero(p, ep->len); + bcopy(finderinfo, p, sizeof(FndrFileInfo)); + p += ep->len; + ep++; + + if ((fdout = open(oFile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + err = errno; + free(pp); + return err; } - if (dumpmap) { - map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); - if (map == NULL) - errx(1, "no memory for file dump list"); - memcpy(map, dumpmap, howmany(oldmax, NBBY)); - free(dumpmap); - dumpmap = map; + + /* write the ASDHeader */ + if (write(fdout, pp, sizeof(ASDHeader) - CORRECT) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; } + /* write the ASDEntries */ + if (write(fdout, pp + sizeof(ASDHeader), thesize - sizeof(ASDHeader)) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; + } + + (void)fchown(fdout, uid, gid); + (void)fchmod(fdout, mode); + close(fdout); + (void)fsetflags(oFile, flags); + utimes(oFile, timep); + free(pp); + return err; } +#endif /* DUMP_MACOSX */ diff --git a/rmt/rmt.c b/rmt/rmt.c index 6f01bcc..1543a7b 100644 --- a/rmt/rmt.c +++ b/rmt/rmt.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: rmt.c,v 1.26 2003/04/08 19:52:37 stelian Exp $"; + "$Id: rmt.c,v 1.27 2003/10/26 16:05:49 stelian Exp $"; #endif /* not linux */ /* @@ -111,9 +111,10 @@ static int rmt_version = 0; #define MTS_FLAGS 'f' #define MTS_BF 'b' -char *checkbuf __P((char *, int)); -void error __P((int)); -void getstring __P((char *)); +static char *checkbuf __P((char *, int)); +static void error __P((int)); +static void getstring __P((char *)); +static unsigned long swaplong __P((unsigned long inv)); #ifdef ERMT char *cipher __P((char *, int, int)); void decrypt __P((void)); @@ -128,6 +129,8 @@ main(int argc, char *argv[]) unsigned long block = 0; char *cp; + int magtape = 0; + #ifdef ERMT if (argc > 1 && strcmp(argv[1], "-d") == 0) decrypt(); /* decrypt stdin to stdout, and exit() */ @@ -176,6 +179,10 @@ top: if (tape < 0) goto ioerror; block = 0; + { + struct mtget mt_stat; + magtape = ioctl(tape, MTIOCGET, (char *)&mt_stat) == 0; + } goto respond; case 'C': @@ -187,11 +194,59 @@ top: block = 0; goto respond; +#ifdef USE_QFA +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 +#endif + case 'L': getstring(count); getstring(pos); DEBUG2("rmtd: L %s %s\n", count, pos); - rval = LSEEK(tape, (OFF_T)atoll(count), atoi(pos)); + if (!magtape) { /* traditional */ + rval = LSEEK(tape, (OFF_T)atoll(count), atoi(pos)); + } + else { + switch (atoi(pos)) { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + rval = LSEEK(tape, (OFF_T)atoll(count), atoi(pos)); + break; +#ifdef USE_QFA + case LSEEK_GET_TAPEPOS: /* QFA */ + case LSEEK_GO2_TAPEPOS: + { + struct mtop buf; + long mtpos; + + buf.mt_op = MTSETDRVBUFFER; + buf.mt_count = MT_ST_BOOLEANS | MT_ST_SCSI2LOGICAL; + if (ioctl(tape, MTIOCTOP, &buf) < 0) { + goto ioerror; + } + + if (atoi(pos) == LSEEK_GET_TAPEPOS) { /* get tapepos */ + if (ioctl(tape, MTIOCPOS, &mtpos) < 0) { + goto ioerror; + } + rval = (OFF_T)mtpos; + } else { + buf.mt_op = MTSEEK; + buf.mt_count = atoi(count); + if (ioctl(tape, MTIOCTOP, &buf) < 0) { + goto ioerror; + } + rval = (OFF_T)buf.mt_count; + } + } + break; +#endif /* USE_QFA */ + default: + errno = EINVAL; + goto ioerror; + } + } if (rval < 0) goto ioerror; goto respond; @@ -254,7 +309,7 @@ top: struct mtop mtop; mtop.mt_op = -1; if (rmt_version) { - /* rmt version 1, assume UNIX client */ + /* rmt version 1, assume UNIX/Solaris/Mac OS X client */ switch (atoi(op)) { #ifdef MTWEOF case 0: @@ -295,6 +350,21 @@ top: case 7: mtop.mt_op = MTNOP; break; +#endif +#ifdef MTRETEN + case 8: + mtop.mt_op = MTRETEN; + break; +#endif +#ifdef MTERASE + case 9: + mtop.mt_op = MTERASE; + break; +#endif +#ifdef MTEOM + case 10: + mtop.mt_op = MTEOM; + break; #endif } if (mtop.mt_op == -1) { @@ -307,8 +377,9 @@ top: mtop.mt_op = atoi(op); } mtop.mt_count = atoi(count); - if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0) + if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0) { goto ioerror; + } rval = mtop.mt_count; } goto respond; @@ -355,8 +426,9 @@ top: goto ioerror; } mtop.mt_count = atoi (count); - if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0) + if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0) { goto ioerror; + } rval = mtop.mt_count; @@ -366,12 +438,33 @@ top: case 'S': /* status */ DEBUG("rmtd: S\n"); { struct mtget mtget; - if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0) + + if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0) { goto ioerror; - rval = sizeof (mtget); - (void)sprintf(resp, "A%lld\n", (long long)rval); - (void)write(1, resp, strlen(resp)); - (void)write(1, (char *)&mtget, sizeof (mtget)); + } + + if (rmt_version) { + rval = sizeof(mtget); + /* assume byte order: + Linux on Intel (little), Solaris on SPARC (big), Mac OS X on PPC (big) + thus need byte swapping from little to big + */ + mtget.mt_type = swaplong(mtget.mt_type); + mtget.mt_resid = swaplong(mtget.mt_resid); + mtget.mt_dsreg = swaplong(mtget.mt_dsreg); + mtget.mt_gstat = swaplong(mtget.mt_gstat); + mtget.mt_erreg = swaplong(mtget.mt_erreg); + mtget.mt_fileno = swaplong(mtget.mt_fileno); + mtget.mt_blkno = swaplong(mtget.mt_blkno); + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + (void)write(1, (char *)&mtget, sizeof (mtget)); + } else { + rval = sizeof (mtget); + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + (void)write(1, (char *)&mtget, sizeof (mtget)); + } goto top; } @@ -379,11 +472,15 @@ top: { char s; struct mtget mtget; + DEBUG ("rmtd: s\n"); + if (read (0, &s, 1) != 1) goto top; + DEBUG1 ("rmtd: s %d\n", s); - if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0) + if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0) { goto ioerror; + } switch (s) { case MTS_TYPE: @@ -418,11 +515,11 @@ top: goto respond; } - case 'V': /* version */ - getstring(op); - DEBUG1("rmtd: V %s\n", op); - rval = 2; - goto respond; + case 'V': /* version */ + getstring(op); + DEBUG1("rmtd: V %s\n", op); + rval = 2; + goto respond; default: DEBUG1("rmtd: garbage command %c\n", c); @@ -438,7 +535,7 @@ ioerror: goto top; } -void getstring(char *bp) +static void getstring(char *bp) { int i; char *cp = bp; @@ -452,7 +549,7 @@ void getstring(char *bp) cp[i] = '\0'; } -char * +static char * checkbuf(char *record, int size) { @@ -472,7 +569,7 @@ checkbuf(char *record, int size) return (record); } -void +static void error(int num) { @@ -480,3 +577,21 @@ error(int num) (void)snprintf(resp, sizeof(resp), "E%d\n%s\n", num, strerror(num)); (void)write(1, resp, strlen(resp)); } + +static unsigned long +swaplong(unsigned long inv) +{ + union lconv { + unsigned long ul; + unsigned char uc[4]; + } *inp, outv; + + inp = (union lconv *)&inv; + + outv.uc[0] = inp->uc[3]; + outv.uc[1] = inp->uc[2]; + outv.uc[2] = inp->uc[1]; + outv.uc[3] = inp->uc[0]; + + return (outv.ul); +} -- 2.39.2