-$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 ??????????????)
====================================================================
different signature. Thanks to Mike Harris <mharris@redhat.com>
for reporting this bug.
+5. Made dump/restore build on Solaris, making possible to
+ restore Linux's "enhanced" tapes. Thanks to Uwe Gohlke
+ <uwe@ugsoft.de> for the patch.
+
+6. Made an extension in the dump tape format capable of saving
+ MacOSX specific inode extensions. Uwe Gohlke <uwe@ugsoft.de>
+ 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)
====================================================================
#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 <config.h>
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
}
}
}
-
- exit(X_ABORT);
+ if (abortifconnerr)
+ exit(X_ABORT);
}
static int
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;
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;
}
(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)
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 <config.h>
#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
#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)))
#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;
#define MAXNAMLEN 255
#endif
+#ifdef sunos
+#define MAXNAMLEN 255
+#endif
+
/*
* For old libc.
*/
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
+
+#ifdef sunos
+#define DT_WHT 14
+#endif
#endif
#ifndef d_fileno
* 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
/*
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 $
*/
/*
#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 */
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 $
*/
/*
#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 */
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 */
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
#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
/*
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_ */
#include <config.h>
#include <compatlfs.h>
+#include <sys/types.h>
#include <stdio.h>
#include <sys/param.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
+#include <sys/cdefs.h>
#include "bylabel.h"
#define PROC_PARTITIONS "/proc/partitions"
#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 <config.h>
+#include <sys/types.h>
#include <compaterr.h>
#include <errno.h>
#include <stdio.h>
#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 <config.h>
+#include <sys/types.h>
#ifndef HAVE_GLOB
* the password file
*/
if (
-#ifndef __linux__
+#if !defined(__linux__) && !defined(sunos)
#ifndef __NETBSD_SYSCALLS
issetugid() != 0 ||
#endif
/* 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
--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]
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
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
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 $
*/
/*-
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();
#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 <config.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#include <fcntl.h>
#ifdef __linux__
#ifdef HAVE_EXT2FS_EXT2_FS_H
#include <ext2fs/ext2_fs.h>
#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 <config.h>
#include <ctype.h>
#include <compaterr.h>
#include <fcntl.h>
+#include <fstab.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ext2fs/ext2fs.h>
#include <sys/stat.h>
#include <bsdcompat.h>
+#include <linux/fs.h> /* for definition of BLKFLSBUF */
#elif defined sunos
#include <sys/vnode.h>
#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.
*/
long long bytes_written = 0; /* total bytes written */
long uncomprblks = 0;/* uncompressed blocks written */
+long smtc_errno;
+
#ifdef __linux__
char *__progname;
#endif
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 |
exit(X_STARTUP);
}
#ifdef BLKFLSBUF
- (void)ioctl(diskfd, BLKFLSBUF);
+ (void)ioctl(diskfd, BLKFLSBUF, 0);
#endif
retval = dump_fs_open(disk, &fs);
if (retval) {
#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 <config.h>
#ifdef __linux__
#include <sys/types.h>
#include <sys/time.h>
+#include <linux/fs.h> /* for definition of BLKFLSBUF */
#include <time.h>
#endif
#include <sys/param.h>
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 */
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
/*
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;
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);
#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);
+ }
+ /* } */
}
}
}
* 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));
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
*/
#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
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);
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 */
#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 <config.h>
writerec(cp, 0);
}
-#if defined __linux__ && !defined(int32_t)
+#if defined(__linux__) && !defined(int32_t)
#define int32_t __s32
#endif
/*
* 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;
#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 <config.h>
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#endif
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#endif
#endif /* __linux__ */
#include <protocols/dumprestore.h>
#ifdef __linux__
#include <endian.h>
#else
+#ifdef sunos
+#include <arpa/nameser_compat.h>
+#else
#include <machine/endian.h>
#endif
+#endif
#include "pathnames.h"
#include "restore.h"
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.
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;
* 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)
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;
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 $
*/
/*-
#include <config.h>
#include <compatlfs.h>
+#ifndef __P
+#include <sys/cdefs.h>
+#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));
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
+
+
+
#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 <config.h>
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#endif
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#endif
#endif /* __linux__ */
#include <protocols/dumprestore.h>
#ifdef __linux__
#include <ext2fs/ext2fs.h>
+#endif
+
+#if defined(__linux__) || defined(sunos)
extern char * __progname;
#endif
#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 <config.h>
#include <compatlfs.h>
+#include <sys/types.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>
#else /* __linux__ */
+#ifdef sunos
+#include <signal.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#include <sys/mtio.h>
+#else
#include <ufs/ufs/dinode.h>
+#endif
#endif /* __linux__ */
#include <protocols/dumprestore.h>
#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;
long long curtapepos;
#endif /* USE_QFA */
+long smtc_errno;
+
#if defined(__linux__) || defined(sunos)
char *__progname;
#endif
/* 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 */
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;
#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);
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");
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 */
#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 <config.h>
#endif
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
+#endif
#endif /* __linux__ */
+
#include <protocols/dumprestore.h>
#include <compaterr.h>
continue;
#ifdef __linux__
(void)fprintf(stderr, "BUG! Should call delwhiteout\n");
+#else
+#ifdef sunos
#else
delwhiteout(ep);
+#endif
#endif
freeentry(ep);
}
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();
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");
#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
+ }
}
}
}
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);
}
#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 */
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;
}
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 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 $
*/
/*
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 \
#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 */
/*
#endif
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
+#endif
#endif /* __linux__ */
#include <errno.h>
#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 <config.h>
#include <compatlfs.h>
+#include <sys/types.h>
#include <errno.h>
#include <compaterr.h>
#include <system.h>
#include <ext2fs/ext2fs.h>
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#define quad_t int64_t
+#include <sys/time.h>
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
+#endif
#endif /* __linux__ */
+#ifdef DUMP_MACOSX
+#include "darwin.h"
+#endif
#include <protocols/dumprestore.h>
#ifdef HAVE_ZLIB
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));
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);
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) {
goto again;
}
}
-#endif
+#endif /* USE_QFA */
return;
}
closemt();
}
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))
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);
}
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;
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));
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
}
}
-#ifdef sunos
-struct timeval
- time_t tv_sec; /* seconds */
- suseconds_t tv_usec; /* and microseconds */
-};
-#endif
int
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);
(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);
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);
/* 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
*/
(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.
*/
}
#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
*/
#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
return err;
}
-typedef struct mt_pos {
- short mt_op;
- int mt_count;
-} MTPosRec, *MTPosPtr;
-
/*
* go to specified position on tape
*/
#ifdef RDUMP
if (host)
- err = (rmtseek(pos, SEEK_SET) < 0);
+ err = (rmtseek((OFF_T)pos, (int)LSEEK_GO2_TAPEPOS) < 0);
else
#endif
{
}
return err;
}
+#endif /* __linux__ */
/*
* read next data from tape to re-sync
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 */
#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 <config.h>
+#include <compatlfs.h>
+#include <sys/types.h>
#include <errno.h>
#include <compaterr.h>
#include <stdio.h>
#ifdef __linux__
#include <sys/time.h>
#include <time.h>
+#include <fcntl.h>
#ifdef HAVE_EXT2FS_EXT2_FS_H
#include <ext2fs/ext2_fs.h>
#else
#include <ext2fs/ext2fs.h>
#include <bsdcompat.h>
#else /* __linux__ */
+#ifdef sunos
+#include <sys/time.h>
+#include <sys/fcntl.h>
+#include <bsdcompat.h>
+#else
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#endif
#endif /* __linux__ */
-
+#ifdef DUMP_MACOSX
+#include "darwin.h"
+#endif
#include "restore.h"
#include "extern.h"
* 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",
}
}
+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
*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));
}
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 */
#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 */
/*
#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));
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() */
if (tape < 0)
goto ioerror;
block = 0;
+ {
+ struct mtget mt_stat;
+ magtape = ioctl(tape, MTIOCGET, (char *)&mt_stat) == 0;
+ }
goto respond;
case 'C':
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;
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:
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) {
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;
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;
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;
}
{ 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:
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);
goto top;
}
-void getstring(char *bp)
+static void getstring(char *bp)
{
int i;
char *cp = bp;
cp[i] = '\0';
}
-char *
+static char *
checkbuf(char *record, int size)
{
return (record);
}
-void
+static void
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);
+}