+Changes between versions 0.4b4 and 0.4b5
+========================================
+
+1. Integrated the changes from FreeBSD-3.1-RELEASE
+ (mostly bug fixes, buffer overruns, dump has now an "automatic
+ tape length calculation" flag, dump/restore can use kerberos now
+ (this is NOT tested), use environment variables for TAPE and
+ RMT etc.).
+
+2. Integrated three RedHat patches ("glibc", "kernel" and "bread" patches)
+
+3. Corrected a bug in restore when using 'C' option with multi-volumes
+ tapes (files splited accros two tapes give "size changed" errors
+ when comparing).
+
+4. Corrected the long standing bug when dumping multiple tapes.
+ This works for me, needs further testing.
Changes between versions 0.4b3 and 0.4b4
========================================
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
resynchronizing itself on a multi-volume dump. Thus, some files are
not restored.
+ Update: this is fixed in 4.0b5, needs succes reports!
+
2. I have tried to minimize changes in the BSD source and some parts
may look ugly. dump/tape.c is really awfull but this is pure BSD
code :-) Maybe, I should replace it with a simpler and cleaner
version.
+
+3. Kerberos mode is _NOT_ tested.
--- /dev/null
+The dump and restore backup suit was ported to Linux's Second
+Extended File System by Rémy Card <card@Linux.EU.Org>
+
+He was the maintainer of the initial versions of dump (up and
+including 0.4b4, released in january 1997).
+
+I decided to continue the developpement and release a new version.
+Rémy didn't respond to any mail I sent to him, so I have
+promoted myself as the new maintainer :)
+
+So, starting with 0.4b5, the new maintainer is me,
+Stelian Pop <pop@cybercable.fr>.
+
See the file INSTALL for installation instructions.
If you encounter problems with the dump and restore backup suite,
-please contact me (card@Linux.EU.Org) and send me a detailled bug report.
+please contact the maintainers and send them a detailled bug report.
David Frey <david@eos.lugs.ch> (the Debian dump maintainer) and the people
from Red Hat Software provided lots of patches.
+Stelian Pop <pop@cybercable.fr> is now the current maintainer (since
+dump-0.4b5).
+
Thanks to people who reported problems with the port, sent patches, and
suggested various improvements.
Here is a partial list of them (if I have forgotten someone, please complain):
-1. Fix the multi-volume problem (is there one after all?, I could not
- reproduce it and some people told me that multi-volume dumps were Ok).
-
-2. Make dump honor the no-dump attribute on directories. Currently, it
+1. Make dump honor the no-dump attribute on directories. Currently, it
honours it only on files. This means that a directory flagged with
the no-dump attribute will be dumped if it contains a file without
the no-dump flag.
-3. Change the way rdump and rrestore call rmt. Currently, rcmd() is used
- but it may be better to call rsh. I have to look at the GNU tar code.
-
-4. Make dump able to backup several directories and/or files in one
+2. Make dump able to backup several directories and/or files in one
invocation, like the SunOS version.
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
-static char sccsid[] = "@(#)dumprmt.c 8.2 (Berkeley) 4/28/95";
+#if 0
+static char sccsid[] = "@(#)dumprmt.c 8.3 (Berkeley) 4/28/95";
+#endif
+static const char rcsid[] =
+ "$Id: dumprmt.c,v 1.2 1999/10/11 12:53:20 stelian Exp $";
#endif /* not lint */
+#ifdef __linux__
+#include <sys/types.h>
+#include <linux/types.h>
+#endif
#include <sys/param.h>
#include <sys/mtio.h>
-#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifdef __linux__
#include <linux/ext2_fs.h>
#include <bsdcompat.h>
+#include <signal.h>
#else
#ifdef sunos
#include <sys/vnode.h>
#endif
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <protocols/dumprestore.h>
#include <ctype.h>
-#include <err.h>
#include <netdb.h>
#include <pwd.h>
-#include <signal.h>
#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
static void rmtgetconn __P((void));
static void rmtgets __P((char *, int));
static int rmtreply __P((char *));
+#ifdef KERBEROS
+int krcmd __P((char **, int /*u_short*/, char *, char *, int *, char *));
+#endif
+static int errfd = -1;
+extern int dokerberos;
extern int ntrec; /* blocking factor on tape */
int
static void
rmtconnaborted()
{
+ msg("Lost connection to remote host.\n");
+ if (errfd != -1) {
+ fd_set r;
+ struct timeval t;
+
+ FD_ZERO(&r);
+ FD_SET(errfd, &r);
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+ if (select(errfd + 1, &r, NULL, NULL, &t)) {
+ int i;
+ char buf[2048];
+
+ if ((i = read(errfd, buf, sizeof(buf) - 1)) > 0) {
+ buf[i] = '\0';
+ msg("on %s: %s%s", rmtpeer, buf,
+ buf[i - 1] == '\n' ? "" : "\n");
+ }
+ }
+ }
- errx(1, "Lost connection to remote host.");
+ exit(X_ABORT);
}
void
rmtgetconn()
{
register char *cp;
+ register const char *rmt;
static struct servent *sp = NULL;
static struct passwd *pwd = NULL;
-#ifdef notdef
- static int on = 1;
-#endif
char *tuser;
int size;
- int maxseg;
+ int throughput;
+ int on;
if (sp == NULL) {
- sp = getservbyname("shell", "tcp");
- if (sp == NULL)
- errx(1, "shell/tcp: unknown service");
+ sp = getservbyname(dokerberos ? "kshell" : "shell", "tcp");
+ if (sp == NULL) {
+ msg("%s/tcp: unknown service\n",
+ dokerberos ? "kshell" : "shell");
+ exit(X_STARTUP);
+ }
pwd = getpwuid(getuid());
- if (pwd == NULL)
- errx(1, "who are you?");
+ if (pwd == NULL) {
+ msg("who are you?\n");
+ exit(X_STARTUP);
+ }
}
if ((cp = strchr(rmtpeer, '@')) != NULL) {
tuser = rmtpeer;
*cp = '\0';
if (!okname(tuser))
- exit(1);
+ exit(X_STARTUP);
rmtpeer = ++cp;
} else
tuser = pwd->pw_name;
- rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
- _PATH_RMT, (int *)0);
+ if ((rmt = getenv("RMT")) == NULL)
+ rmt = _PATH_RMT;
+ msg("");
+#ifdef KERBEROS
+ if (dokerberos)
+ rmtape = krcmd(&rmtpeer, sp->s_port, tuser, rmt, &errfd,
+ (char *)0);
+ else
+#endif
+ rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name,
+ tuser, rmt, &errfd);
+ if (rmtape < 0) {
+ msg("login to %s as %s failed.\n", rmtpeer, tuser);
+ return;
+ }
+ (void)fprintf(stderr, "Connection to %s established.\n", rmtpeer);
size = ntrec * TP_BSIZE;
if (size > 60 * 1024) /* XXX */
size = 60 * 1024;
setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
size -= TP_BSIZE;
(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
- maxseg = 1024;
- if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
- &maxseg, sizeof (maxseg)) < 0)
- perror("TCP_MAXSEG setsockopt");
-
-#ifdef notdef
+ throughput = IPTOS_THROUGHPUT;
+ if (setsockopt(rmtape, IPPROTO_IP, IP_TOS,
+ &throughput, sizeof(throughput)) < 0)
+ perror("IP_TOS:IPTOS_THROUGHPUT setsockopt");
+ on = 1;
if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
perror("TCP_NODELAY setsockopt");
-#endif
}
static int
for (cp = cp0; *cp; cp++) {
c = *cp;
if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
- warnx("invalid user name: %s", cp0);
+ msg("invalid user name %s\n", cp0);
return (0);
}
}
{
char buf[256];
- (void)sprintf(buf, "O%s\n%d\n", tape, mode);
+ (void)snprintf(buf, sizeof (buf), "O%.226s\n%d\n", tape, mode);
rmtstate = TS_OPEN;
return (rmtcall(tape, buf));
}
{
char line[30];
int n, i, cc;
- extern errno;
- (void)sprintf(line, "R%d\n", count);
+ (void)snprintf(line, sizeof (line), "R%d\n", count);
n = rmtcall("read", line);
- if (n < 0) {
- errno = n;
- return (-1);
- }
+ if (n < 0)
+ /* rmtcall() properly sets errno for us on errors. */
+ return (n);
for (i = 0; i < n; i += cc) {
cc = read(rmtape, buf+i, n - i);
- if (cc <= 0) {
+ if (cc <= 0)
rmtconnaborted();
- }
}
return (n);
}
{
char line[30];
- (void)sprintf(line, "W%d\n", count);
+ (void)snprintf(line, sizeof (line), "W%d\n", count);
write(rmtape, line, strlen(line));
write(rmtape, buf, count);
return (rmtreply("write"));
{
char line[30];
- (void)sprintf(line, "W%d\n", count);
+ (void)snprintf(line, sizeof (line), "W%d\n", count);
write(rmtape, line, strlen(line));
}
{
char line[80];
- (void)sprintf(line, "L%d\n%d\n", offset, pos);
+ (void)snprintf(line, sizeof (line), "L%d\n%d\n", offset, pos);
return (rmtcall("seek", line));
}
if (count < 0)
return (-1);
- (void)sprintf(buf, "I%d\n%d\n", cmd, count);
+ (void)snprintf(buf, sizeof (buf), "I%d\n%d\n", cmd, count);
return (rmtcall("ioctl", buf));
}
{
register char *cp;
char code[30], emsg[BUFSIZ];
+ extern int errno;
rmtgets(code, sizeof (code));
if (*code == 'E' || *code == 'F') {
rmtgets(emsg, sizeof (emsg));
msg("%s: %s", cmd, emsg);
- if (*code == 'F') {
+ errno = atoi(code + 1);
+ if (*code == 'F')
rmtstate = TS_CLOSED;
- return (-1);
- }
return (-1);
}
if (*code != 'A') {
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
#include <config.h>
+#include <sys/time.h>
#define __dead volatile
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
* SUCH DAMAGE.
*
* @(#)err.h 8.1 (Berkeley) 6/2/93
+ * $Id: err.h,v 1.2 1999/10/11 12:53:20 stelian Exp $
*/
#ifndef _ERR_H_
__BEGIN_DECLS
__dead void err __P((int, const char *, ...));
__dead void verr __P((int, const char *, _BSD_VA_LIST_));
+__dead void errc __P((int, int, const char *, ...));
+__dead void verrc __P((int, int, const char *, _BSD_VA_LIST_));
__dead void errx __P((int, const char *, ...));
__dead void verrx __P((int, const char *, _BSD_VA_LIST_));
void warn __P((const char *, ...));
void vwarn __P((const char *, _BSD_VA_LIST_));
+void warnc __P((int, const char *, ...));
+void vwarnc __P((int, const char *, _BSD_VA_LIST_));
void warnx __P((const char *, ...));
void vwarnx __P((const char *, _BSD_VA_LIST_));
+void err_set_file __P((void *));
+void err_set_exit __P((void (*)(int)));
__END_DECLS
#endif /* !_ERR_H_ */
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
#define GLOB_NOSORT 0x0020 /* Don't sort. */
-/* #ifndef _POSIX_SOURCE */
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
-/* #endif */
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
#define GLOB_ABEND (-2) /* Unignored error. */
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
#define _PATH_DTMP "/etc/dtmp"
#define _PATH_DUMPDATES "/etc/dumpdates"
#define _PATH_LOCK "/tmp/dumplockXXXXXX"
-#define _PATH_RMT "rmt"
+#define _PATH_RMT "/etc/rmt" /* path on remote host */
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
* @(#)dumprestore.h 8.2 (Berkeley) 1/21/94
*/
-#ifndef _DUMPRESTORE_H_
-#define _DUMPRESTORE_H_
+#ifndef _PROTOCOLS_DUMPRESTORE_H_
+#define _PROTOCOLS_DUMPRESTORE_H_
/*
* TP_BSIZE is the size of file blocks on the dump tapes.
union u_spcl {
char dummy[TP_BSIZE];
struct s_spcl {
- __s32 c_type; /* record type (see below) */
- __u32 c_date; /* date of this dump */
- __u32 c_ddate; /* date of previous dump */
- __s32 c_volume; /* dump volume number */
+ int32_t c_type; /* record type (see below) */
+ time_t c_date; /* date of this dump */
+ time_t c_ddate; /* date of previous dump */
+ int32_t c_volume; /* dump volume number */
daddr_t c_tapea; /* logical block of this record */
ino_t c_inumber; /* number of inode */
- __s32 c_magic; /* magic number (see above) */
- __s32 c_checksum; /* record checksum */
+ int32_t c_magic; /* magic number (see above) */
+ int32_t c_checksum; /* record checksum */
#ifdef __linux__
struct new_bsd_inode c_dinode;
#else
struct dinode c_dinode; /* ownership and mode of inode */
#endif
- __s32 c_count; /* number of valid c_addr entries */
+ int32_t c_count; /* number of valid c_addr entries */
char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
char c_label[LBLSIZE]; /* dump label */
- __s32 c_level; /* level of this dump */
+ int32_t c_level; /* level of this dump */
char c_filesys[NAMELEN]; /* name of dumpped file system */
char c_dev[NAMELEN]; /* name of dumpped device */
char c_host[NAMELEN]; /* name of dumpped host */
- __s32 c_flags; /* additional information */
- __s32 c_firstrec; /* first record on volume */
- __s32 c_spare[32]; /* reserved for future uses */
+ int32_t c_flags; /* additional information */
+ int32_t c_firstrec; /* first record on volume */
+ int32_t c_spare[32]; /* reserved for future uses */
} s_spcl;
} u_spcl;
#define spcl u_spcl.s_spcl
+++ /dev/null
-/*
- * Ported to Linux's Second Extended File System as part of the
- * dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
- *
- */
-
-/*
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Arthur David Olson of the National Cancer Institute.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)tzfile.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _TZFILE_H_
-#define _TZFILE_H_
-
-/*
- * Information about time zone files.
- */
- /* Time zone object file directory */
-#define TZDIR "/usr/share/zoneinfo"
-#define TZDEFAULT "/etc/localtime"
-#define TZDEFRULES "posixrules"
-
-/*
-** Each file begins with. . .
-*/
-
-struct tzhead {
- char tzh_reserved[24]; /* reserved for future use */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
-};
-
-/*
-** . . .followed by. . .
-**
-** tzh_timecnt (char [4])s coded transition times a la time(2)
-** tzh_timecnt (unsigned char)s types of local time starting at above
-** tzh_typecnt repetitions of
-** one (char [4]) coded GMT offset in seconds
-** one (unsigned char) used to set tm_isdst
-** one (unsigned char) that's an abbreviation list index
-** tzh_charcnt (char)s '\0'-terminated zone abbreviations
-** tzh_leapcnt repetitions of
-** one (char [4]) coded leap second transition times
-** one (char [4]) total correction after above
-** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
-** time is standard time, if FALSE,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-*/
-
-/*
-** In the current implementation, "tzset()" refuses to deal with files that
-** exceed any of the limits below.
-*/
-
-/*
-** The TZ_MAX_TIMES value below is enough to handle a bit more than a
-** year's worth of solar time (corrected daily to the nearest second) or
-** 138 years of Pacific Presidential Election time
-** (where there are three time zone transitions every fourth year).
-*/
-#define TZ_MAX_TIMES 370
-
-#define NOSOLAR /* 4BSD doesn't currently handle solar time */
-
-#ifndef NOSOLAR
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#else
-#define TZ_MAX_TYPES 10 /* Maximum number of local time types */
-#endif
-
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
-
-#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-
-#define SECSPERMIN 60
-#define MINSPERHOUR 60
-#define HOURSPERDAY 24
-#define DAYSPERWEEK 7
-#define DAYSPERNYEAR 365
-#define DAYSPERLYEAR 366
-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
-#define MONSPERYEAR 12
-
-#define TM_SUNDAY 0
-#define TM_MONDAY 1
-#define TM_TUESDAY 2
-#define TM_WEDNESDAY 3
-#define TM_THURSDAY 4
-#define TM_FRIDAY 5
-#define TM_SATURDAY 6
-
-#define TM_JANUARY 0
-#define TM_FEBRUARY 1
-#define TM_MARCH 2
-#define TM_APRIL 3
-#define TM_MAY 4
-#define TM_JUNE 5
-#define TM_JULY 6
-#define TM_AUGUST 7
-#define TM_SEPTEMBER 8
-#define TM_OCTOBER 9
-#define TM_NOVEMBER 10
-#define TM_DECEMBER 11
-
-#define TM_YEAR_BASE 1900
-
-#define EPOCH_YEAR 1970
-#define EPOCH_WDAY TM_THURSDAY
-
-/*
-** Accurate only for the past couple of centuries;
-** that will probably do.
-*/
-
-#define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0)
-
-#endif /* !_TZFILE_H_ */
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ * From: @(#)err.c 8.1 (Berkeley) 6/4/93
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] =
+ "$Id: err.c,v 1.2 1999/10/11 12:53:21 stelian Exp $";
+#endif /* LIBC_RCS and not lint */
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#ifdef __STDC__
#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include <config.h>
extern char *__progname; /* Program name, from crt0. */
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first. However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void
+err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+
#ifndef HAVE_ERR
__dead void
-#ifdef __STDC__
err(int eval, const char *fmt, ...)
-#else
-err(eval, fmt, va_alist)
- int eval;
- const char *fmt;
- va_dcl
-#endif
{
va_list ap;
-#if __STDC__
va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- verr(eval, fmt, ap);
+ verrc(eval, errno, fmt, ap);
va_end(ap);
}
#endif
const char *fmt;
va_list ap;
{
- int sverrno;
+ verrc(eval, errno, fmt, ap);
+}
+#endif
+
+#ifndef HAVE_ERRC
+__dead void
+errc(int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, code, fmt, ap);
+ va_end(ap);
+}
+#endif
- sverrno = errno;
- (void)fprintf(stderr, "%s: ", __progname);
+#ifndef HAVE_VERRC
+__dead void
+verrc(eval, code, fmt, ap)
+ int eval;
+ int code;
+ const char *fmt;
+ va_list ap;
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, ": ");
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
}
- (void)fprintf(stderr, "%s\n", strerror(sverrno));
+ fprintf(err_file, "%s\n", strerror(code));
+ if (err_exit)
+ err_exit(eval);
exit(eval);
}
#endif
#ifndef HAVE_ERRX
__dead void
-#if __STDC__
errx(int eval, const char *fmt, ...)
-#else
-errx(eval, fmt, va_alist)
- int eval;
- const char *fmt;
- va_dcl
-#endif
{
va_list ap;
-#if __STDC__
va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
verrx(eval, fmt, ap);
va_end(ap);
}
const char *fmt;
va_list ap;
{
- (void)fprintf(stderr, "%s: ", __progname);
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, "\n");
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
exit(eval);
}
#endif
#ifndef HAVE_WARN
void
-#if __STDC__
warn(const char *fmt, ...)
-#else
-warn(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
{
va_list ap;
-#if __STDC__
va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- vwarn(fmt, ap);
+ vwarnc(errno, fmt, ap);
va_end(ap);
}
#endif
const char *fmt;
va_list ap;
{
- int sverrno;
+ vwarnc(errno, fmt, ap);
+}
+#endif
+
+#ifndef HAVE_WARNC
+void
+warnc(int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+#endif
- sverrno = errno;
- (void)fprintf(stderr, "%s: ", __progname);
+#ifndef HAVE_VWARNC
+void
+vwarnc(code, fmt, ap)
+ int code;
+ const char *fmt;
+ va_list ap;
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, ": ");
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
}
- (void)fprintf(stderr, "%s\n", strerror(sverrno));
+ fprintf(err_file, "%s\n", strerror(code));
}
#endif
#ifndef HAVE_WARNX
void
-#ifdef __STDC__
warnx(const char *fmt, ...)
-#else
-warnx(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
{
va_list ap;
-#ifdef __STDC__
va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
vwarnx(fmt, ap);
va_end(ap);
}
const char *fmt;
va_list ap;
{
- (void)fprintf(stderr, "%s: ", __progname);
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, "\n");
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
}
#endif
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
struct fstab *
getfsent()
{
- if (!_fs_fp && !setfsent() || !fstabscan())
+ if ((!_fs_fp && !setfsent()) || !fstabscan())
return((struct fstab *)NULL);
return(&_fs_fstab);
}
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
* GLOB_TILDE:
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
- * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
static int glob2 __P((Char *, Char *, Char *, glob_t *));
static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
static int globextend __P((const Char *, glob_t *));
-static const Char * globtilde __P((const Char *, Char *, glob_t *));
+static const Char * globtilde __P((const Char *, Char *, size_t, glob_t *));
static int globexp1 __P((const Char *, glob_t *));
static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
static int match __P((Char *, Char *, Char *));
bufend = bufnext + MAXPATHLEN;
if (flags & GLOB_QUOTE) {
/* Protect the quoted characters. */
- while (bufnext < bufend && (c = *patnext++) != EOS)
+ while (bufnext < bufend && (c = *patnext++) != EOS)
if (c == QUOTE) {
if ((c = *patnext++) == EOS) {
c = QUOTE;
else
*bufnext++ = c;
}
- else
- while (bufnext < bufend && (c = *patnext++) != EOS)
+ else
+ while (bufnext < bufend && (c = *patnext++) != EOS)
*bufnext++ = c;
*bufnext = EOS;
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
continue;
if (*pe == EOS) {
- /*
+ /*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
continue;
if (*pm == EOS) {
- /*
+ /*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
/* Append the current string */
for (lm = ls; (pl < pm); *lm++ = *pl++)
continue;
- /*
+ /*
* Append the rest of the pattern after the
* closing brace
*/
* expand tilde from the passwd file.
*/
static const Char *
-globtilde(pattern, patbuf, pglob)
+globtilde(pattern, patbuf, patbuf_len, pglob)
const Char *pattern;
Char *patbuf;
+ size_t patbuf_len;
glob_t *pglob;
{
struct passwd *pwd;
char *h;
const Char *p;
- Char *b;
+ Char *b, *eb;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
- /* Copy up to the end of the string or / */
- for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
- *h++ = *p++)
+ /*
+ * Copy up to the end of the string or /
+ */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, h = (char *) patbuf;
+ h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
continue;
*h = EOS;
if (((char *) patbuf)[0] == EOS) {
- /*
- * handle a plain ~ or ~/ by expanding $HOME
- * first and then trying the password file
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME first if
+ * we're not running setuid or setgid) and then trying
+ * the password file
*/
- if ((h = getenv("HOME")) == NULL) {
- if ((pwd = getpwuid(getuid())) == NULL)
- return pattern;
- else
+ if (
+#ifndef __linux__
+#ifndef __NETBSD_SYSCALLS
+ issetugid() != 0 ||
+#endif
+#endif
+ (h = getenv("HOME")) == NULL) {
+ if (((h = getlogin()) != NULL &&
+ (pwd = getpwnam(h)) != NULL) ||
+ (pwd = getpwuid(getuid())) != NULL)
h = pwd->pw_dir;
+ else
+ return pattern;
}
}
else {
}
/* Copy the home directory */
- for (b = patbuf; *h; *b++ = *h++)
+ for (b = patbuf; b < eb && *h; *b++ = *h++)
continue;
-
+
/* Append the rest of the pattern */
- while ((*b++ = *p++) != EOS)
+ while (b < eb && (*b++ = *p++) != EOS)
continue;
+ *b = EOS;
return patbuf;
}
-
+
/*
* The main glob() routine: compiles the pattern (optionally processing
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN+1];
- qpatnext = globtilde(pattern, patbuf, pglob);
+ qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char),
+ pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
break;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
- /* collapse adjacent stars to one,
+ /* collapse adjacent stars to one,
* to avoid exponential behavior
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
return(err);
/*
- * If there was no match we are going to append the pattern
+ * If there was no match we are going to append the pattern
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
* and the pattern did not contain any magic characters
* GLOB_NOMAGIC is there just for compatibility with csh.
*/
- if (pglob->gl_pathc == oldpathc &&
- ((pglob->gl_flags & GLOB_NOCHECK) ||
+ if (pglob->gl_pathc == oldpathc &&
+ ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR))))
return(globextend(pattern, pglob));
- else if (!(pglob->gl_flags & GLOB_NOSORT))
+ else if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
return(0);
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob))
return(0);
-
+
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
|| (S_ISLNK(sb.st_mode) &&
*pathend = EOS;
errno = 0;
-
+
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
/* TODO: don't call for ENOENT or ENOTDIR? */
if (pglob->gl_errfunc) {
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
- for (sc = (u_char *) dp->d_name, dc = pathend;
+ for (sc = (u_char *) dp->d_name, dc = pathend;
(*dc++ = *sc++) != EOS;)
continue;
if (!match(pathend, pattern, restpattern)) {
const Char *p;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- pathv = pglob->gl_pathv ?
+ pathv = pglob->gl_pathv ?
realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL)
return(copy == NULL ? GLOB_NOSPACE : 0);
}
-
/*
* pattern matching function for filenames. Each occurrence of the *
* pattern causes a recursion level.
case M_ALL:
if (pat == patend)
return(1);
- do
+ do
if (match(name, pat, patend))
return(1);
while (*name++ != EOS);
}
#ifdef DEBUG
-static void
+static void
qprintf(str, s)
const char *str;
register Char *s;
/* Define if you have the err function. */
#undef HAVE_ERR
+/* Define if you have the errc function. */
+#undef HAVE_ERRC
+
/* Define if you have the errx function. */
#undef HAVE_ERRX
/* Define if you have the verr function. */
#undef HAVE_VERR
+/* Define if you have the verrc function. */
+#undef HAVE_VERRC
+
/* Define if you have the verrx function. */
#undef HAVE_VERRX
/* Define if you have the vwarn function. */
#undef HAVE_VWARN
+/* Define if you have the vwarnc function. */
+#undef HAVE_VWARNC
+
/* Define if you have the vwarnx function. */
#undef HAVE_VWARNX
/* Define if you have the warn function. */
#undef HAVE_WARN
+/* Define if you have the warnc function. */
+#undef HAVE_WARNC
+
/* Define if you have the warnx function. */
#undef HAVE_WARNX
# We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
basic_machine=i586-intel
;;
- pentium-* | p5-* | p6-*)
+ pentium-* | p5-* | p6-* | i686-* )
# We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
{ echo "configure: error: You need to install the Ext2fs libraries from the E2fsprogs distribution first" 1>&2; exit 1; }
fi
-for ac_func in err errx verr verrx vwarn vwarnx warn warnx realpath
+for ac_func in err errc errx verr verrc verrx vwarn vwarnc vwarnx warn warnc warnx realpath
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1529: checking for $ac_func" >&5
dnl
dnl Check for library functions
dnl
-AC_CHECK_FUNCS(err errx verr verrx vwarn vwarnx warn warnx realpath)
+AC_CHECK_FUNCS(err errc errx verr verrc verrx vwarn vwarnc vwarnx warn warnc warnx realpath)
dnl
dnl Check for types
Begin3
Title: dump and restore for Ext2fs
-Version: 0.4b4
-Entered-date: 17JAN97
+Version: 0.4b5
+Entered-date: 22SEP99
Description: Port of the 4.4BSD dump and restore backup suite
Keywords: backup, filesystem, Ext2fs
Author: University of California, Berkeley
-Maintained-by: card@Linux.EU.Org (Remy Card)
+Maintained-by: pop@captimark.fr (Stelian Pop)
Primary-site: tsx-11.mit.edu /pub/linux/ALPHA/ext2fs
- 126kB dump-0.4b4.tar.gz
+ 132kB dump-0.4b5.tar.gz
627 dump.lsm
Alternate-site:
Original-site: ftp.freebsd.org /pub/bsd-sources/4.4BSD-Lite2/sbin
dump/*
restore/*
-Platforms: linux 2.0.x, e2fsprogs 1.06
+Platforms: linux 2.0.x, linux 2.2.x, e2fsprogs 1.14
Copying-policy: BSD
End
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
+.\" must display the following acknowledgment:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" SUCH DAMAGE.
.\"
.\" @(#)dump.8 8.3 (Berkeley) 5/1/95
+.\" $Id: dump.8,v 1.2 1999/10/11 12:53:21 stelian Exp $
.\"
.Dd May 1, 1995
.Dt DUMP 8
.Nd filesystem backup
.Sh SYNOPSIS
.Nm dump
-.Op Fl 0123456789cnu
+.Op Fl 0123456789acknu
.Op Fl B Ar records
.Op Fl b Ar blocksize
.Op Fl d Ar density
.Op Fl f Ar file
.Op Fl h Ar level
+.Op Fl L Ar label
.Op Fl s Ar feet
.Op Fl T Ar date
.Ar filesystem
.Nm dump
-.Op Fl 0123456789cnu
+.Op Fl 0123456789acknu
.Op Fl B Ar records
.Op Fl b Ar blocksize
.Op Fl d Ar density
.Op Fl f Ar file
.Op Fl h Ar level
+.Op Fl L Ar label
.Op Fl s Ar feet
.Op Fl T Ar date
.Ar directory
A dump that is larger than the output medium is broken into
multiple volumes.
On most media the size is determined by writing until an
-end-of-media indication is returned.
+end-of-media indication is returned. This can be enforced
+by using the
+.Fl a
+option.
+.Pp
On media that cannot reliably return an end-of-media indication
(such as some cartridge tape drives)
each volume is of a fixed size;
after prompting the operator to change media.
.Pp
The following options are supported by
-.Nm dump :
+.Nm Ns :
.Bl -tag -width Ds
.It Fl 0\-9
Dump levels.
incremental backup,
tells dump to
copy all files new or modified since the
-last dump of the same or lower level.
-The default level is 9.
+last dump of any lower level.
+The default level is 0.
.It Fl B Ar records
-The number of dump records per volume.
+The number of 1 KB blocks per volume.
This option overrides the calculation of tape size
based on length and density.
+.It Fl a
+.Dq auto-size .
+Bypass all tape length considerations, and enforce writing
+until an end-of-media indication is returned. This fits best
+for most modern tape drives. Use of this option is particularly
+recommended when appending to an existing tape, or using a tape
+drive with hardware compression (where you can never be sure about
+the compression ratio).
.It Fl b Ar blocksize
The number of kilobytes per dump record.
.It Fl c
-Modify the calculation of the default density and tape size to be more
-appropriate for cartridge tapes.
+Change the defaults for use with a cartridge tape drive, with a density
+of 8000 bpi, and a length of 1700 feet.
+.It Fl h Ar level
+Honor the user
+.Dq nodump
+flag
+.Dp Dv UF_NODUMP
+only for dumps at or above the given
+.Ar level .
+The default honor level is 1,
+so that incremental backups omit such files
+but full backups retain them.
.It Fl d Ar density
Set tape density to
.Ar density .
.Pa /dev/rmt12
(a tape drive),
.Pa /dev/rsd1c
-(a disk drive),
+(a floppy disk drive),
an ordinary file,
or
.Ql Fl
.Dq host:file ,
or
.Dq user@host:file ,
-.Nm dump
+.Nm
writes to the named file on the remote host using
.Xr rmt 8 .
-.It Fl h Ar level
-Honor the user
-.Dq nodump
-flag
-.Dp Dv UF_NODUMP
-only for dumps at or above the given
-.Ar level .
-The default honor level is 1,
-so that incremental backups omit such files
-but full backups retain them.
+The default path name of the remote
+.Xr rmt 8
+program is
+.\" rmt path, is the path on the remote host
+.Pa /etc/rmt ;
+this can be overridden by the environment variable
+.Ev RMT .
+.It Fl k
+Use Kerberos authentication to talk to remote tape servers. (Only
+available if this option was enabled when
+.Nm
+was compiled.)
+.It Fl L Ar label
+The user-supplied text string
+.Ar label
+is placed into the dump header, where tools like
+.Xr restore 8
+and
+.Xr file 1
+can access it.
+Note that this label is limited
+to be at most LBLSIZE (currently 16) characters, which must include
+the terminating
+.Ql \e0 .
.It Fl n
Whenever
-.Nm dump
+.Nm
requires operator attention,
notify all operators in the group
.Dq operator
Attempt to calculate the amount of tape needed
at a particular density.
If this amount is exceeded,
-.Nm dump
+.Nm
prompts for a new tape.
It is recommended to be a bit conservative on this option.
The default tape length is 2300 feet.
The
.Fl W
option causes
-.Nm dump
+.Nm
to print out, for each file system in
.Pa /etc/dumpdates
the most recent dump date and level,
If the
.Fl W
option is set, all other options are ignored, and
-.Nm dump
+.Nm
exits immediately.
.It Fl w
Is like W, but prints only those filesystems which need to be dumped.
In addition to alerting all operators implied by the
.Fl n
key,
-.Nm dump
+.Nm
interacts with the operator on
.Em dump's
control terminal at times when
-.Nm dump
+.Nm
can no longer proceed,
or if something is grossly wrong.
All questions
-.Nm dump
+.Nm
poses
.Em must
be answered by typing
appropriately.
.Pp
Since making a dump involves a lot of time and effort for full dumps,
-.Nm dump
+.Nm
checkpoints itself at the start of each tape volume.
If writing that volume fails for some reason,
-.Nm dump
+.Nm
will,
with operator permission,
restart itself from the checkpoint
The output is verbose,
so that others know that the terminal
controlling
-.Nm dump
+.Nm
is busy,
and will be for some time.
.Pp
.Pp
After several months or so, the daily and weekly tapes should get
rotated out of the dump cycle and fresh tapes brought in.
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TAPE
+If no -f option was specified,
+.Nm
+will use the device specified via
+.Ev TAPE
+as the dump device.
+.Ev TAPE
+may be of the form
+.Qq tapename ,
+.Qq host:tapename ,
+or
+.Qq user@host:tapename .
+.It Ev RMT
+The environment variable
+.Ev RMT
+will be used to determine the pathname of the remote
+.Xr rmt 8
+program.
.Sh FILES
.Bl -tag -width /etc/dumpdates -compact
.It Pa /dev/rmt8
.Em operator
.El
.Sh SEE ALSO
+.Xr fstab 5 ,
.Xr restore 8 ,
-.Xr rmt 8 ,
-.Xr dump 5 ,
-.Xr fstab 5
+.Xr rmt 8
.Sh DIAGNOSTICS
Many, and verbose.
.Pp
.Pa /etc/fstab .
.Pp
It would be nice if
-.Nm dump
+.Nm
knew about the dump sequence,
kept track of the tapes scribbled on,
told the operator which tape to mount when,
and provided more assistance
for the operator running
.Xr restore .
+.Pp
+.Nm Dump
+cannot do remote backups without being run as root, due to its
+security history. This will be fixed in a later version of
+.Bx Free .
+Presently, it works if you set it setuid (like it used to be), but this
+might constitute a security risk.
.Sh HISTORY
A
-.Nm dump
-command appeared in Version 6 AT&T UNIX.
+.Nm
+command appeared in
+.At v6 .
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
long asize; /* number of 0.1" units written on current tape */
int etapes; /* estimated number of tapes */
int nonodump; /* if set, do not honor UF_NODUMP user flags */
+int unlimited; /* if set, write to end of medium */
int notify; /* notify operator flag */
int blockswritten; /* number of blocks written on current tape */
int tapeno; /* current tape number */
time_t tstart_writing; /* when started writing the first tape block */
+time_t tend_writing; /* after writing the last tape block */
#ifdef __linux__
-time_t tend_writing; /* after writing the last tape block */
ext2_filsys fs;
#else
struct fs *sblock; /* the file system super block */
/* file dumping routines */
void blksout __P((daddr_t *blkp, int frags, ino_t ino));
-void bread __P((daddr_t blkno, char *buf, int size));
+void bread __P((daddr_t blkno, char *buf, int size));
void dumpino __P((struct dinode *dp, ino_t ino));
#ifdef __linux__
void dumpdirino __P((struct dinode *dp, ino_t ino));
* Exit status codes
*/
#define X_FINOK 0 /* normal exit */
+#define X_STARTUP 1 /* startup error */
#define X_REWRITE 2 /* restart writing from the check point */
#define X_ABORT 3 /* abort dump; don't attempt checkpointing */
extern char *strcat();
extern time_t time();
extern void endgrent();
-extern __dead void exit();
+extern void exit();
extern off_t lseek();
extern const char *strerror();
#endif
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)itime.c 8.1 (Berkeley) 6/5/93";
+#endif
+static const char rcsid[] =
+ "$Id: itime.c,v 1.2 1999/10/11 12:53:22 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <linux/ext2_fs.h>
#include <bsdcompat.h>
#include <sys/file.h>
+#include <unistd.h>
#else
#ifdef sunos
#include <sys/vnode.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#endif
#ifdef __linux__
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95";
+#endif
+static const char rcsid[] =
+ "$Id: main.c,v 1.2 1999/10/11 12:53:22 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
-#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <signal.h>
int notify = 0; /* notify operator flag */
int blockswritten = 0; /* number of blocks written on current tape */
int tapeno = 0; /* current tape number */
-int density = 0; /* density in bytes/0.1" */
+int density = 0; /* density in bytes/0.1" " <- this is for hilit19 */
int ntrec = NTREC; /* # tape blocks in each tape record */
int cartridge = 0; /* Assume non-cartridge tape */
+int dokerberos = 0; /* Use Kerberos authentication */
long dev_bsize = 1; /* recalculated below */
long blocksperfile; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
char *argv[];
{
register ino_t ino;
- register int dirty;
+ register int dirty;
register struct dinode *dp;
register struct fstab *dt;
register char *map;
char directory[NAME_MAX];
char pathname[NAME_MAX];
#endif
+ char labelstr[LBLSIZE];
spcl.c_date = 0;
#ifdef __linux__
#endif
tsize = 0; /* Default later, based on 'c' option for cart tapes */
- tape = _PATH_DEFTAPE;
+ if ((tape = getenv("TAPE")) == NULL)
+ tape = _PATH_DEFTAPE;
dumpdates = _PATH_DUMPDATES;
temp = _PATH_DTMP;
+ strcpy(labelstr, "none"); /* XXX safe strcpy. */
if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0)
quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
level = '0';
+
if (argc < 2)
usage();
obsolete(&argc, &argv);
- while ((ch = getopt(argc, argv, "0123456789B:b:cd:f:h:ns:T:uWw")) != -1) switch (ch) {
+#ifdef KERBEROS
+#define optstring "0123456789aB:b:cd:f:h:kL:ns:T:uWw"
+#else
+#define optstring "0123456789aB:b:cd:f:h:L:ns:T:uWw"
+#endif
+ while ((ch = getopt(argc, argv, optstring)) != -1)
+#undef optstring
+ switch (ch) {
/* dump level */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
level = ch;
break;
+ case 'a': /* `auto-size', Write to EOM. */
+ unlimited = 1;
+ break;
+
case 'B': /* blocks per output file */
- blocksperfile = numarg("blocks per file", 1L, 0L);
+ blocksperfile = numarg("number of blocks per file",
+ 1L, 0L);
break;
case 'b': /* blocks per tape write */
- ntrec = numarg("blocks per write", 1L, 1000L);
+ ntrec = numarg("number of blocks per write",
+ 1L, 1000L);
break;
case 'c': /* Tape is cart. not 9-track */
honorlevel = numarg("honor level", 0L, 10L);
break;
+#ifdef KERBEROS
+ case 'k':
+ dokerberos = 1;
+ break;
+#endif
+
+ case 'L':
+ /*
+ * Note that although there are LBLSIZE characters,
+ * the last must be '\0', so the limit on strlen()
+ * is really LBLSIZE-1.
+ */
+ strncpy(labelstr, optarg, LBLSIZE);
+ labelstr[LBLSIZE-1] = '\0';
+ if (strlen(optarg) > LBLSIZE-1) {
+ msg(
+ "WARNING Label `%s' is larger than limit of %d characters.\n",
+ optarg, LBLSIZE-1);
+ msg("WARNING: Using truncated label `%s'.\n",
+ labelstr);
+ }
+ break;
+
case 'n': /* notify operators */
notify = 1;
break;
if (spcl.c_ddate < 0) {
(void)fprintf(stderr, "bad time \"%s\"\n",
optarg);
- exit(X_ABORT);
+ exit(X_STARTUP);
}
Tflag = 1;
lastlevel = '?';
+ argc--;
+ argv++;
+ break;
case 'u': /* update /etc/dumpdates */
uflag = 1;
case 'W': /* what to do */
case 'w':
lastdump(ch);
- exit(0); /* do nothing else */
+ exit(X_FINOK); /* do nothing else */
default:
usage();
if (argc < 1) {
(void)fprintf(stderr, "Must specify disk or filesystem\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
}
disk = *argv++;
argc--;
while (argc--)
(void)fprintf(stderr, " %s", *argv++);
(void)fprintf(stderr, "\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
}
if (Tflag && uflag) {
(void)fprintf(stderr,
"You cannot use the T and u flags together.\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
}
if (strcmp(tape, "-") == 0) {
pipeout++;
if (blocksperfile)
blocksperfile = blocksperfile / ntrec * ntrec; /* round down */
- else {
+ else if (!unlimited) {
/*
* Determine how to default tape size and density
*
* 9-track 6250 bpi (625 bytes/.1") 2300 ft.
* cartridge 8000 bpi (100 bytes/.1") 1700 ft.
* (450*4 - slop)
+ * hilit19 hits again: "
*/
if (density == 0)
density = cartridge ? 100 : 160;
tape = strchr(host, ':');
*tape++ = '\0';
#ifdef RDUMP
+ if (index(tape, '\n')) {
+ (void)fprintf(stderr, "invalid characters in tape\n");
+ exit(X_STARTUP);
+ }
if (rmthost(host) == 0)
- exit(X_ABORT);
+ exit(X_STARTUP);
#else
(void)fprintf(stderr, "remote dump not enabled\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
#endif
}
(void)setuid(getuid()); /* rmthost() is the only reason to be setuid */
NAMELEN);
}
#endif
- (void)strcpy(spcl.c_label, "none");
+ spcl.c_dev[NAMELEN-1]='\0';
+ spcl.c_filesys[NAMELEN-1]='\0';
+ (void)strncpy(spcl.c_label, labelstr, sizeof(spcl.c_label) - 1);
(void)gethostname(spcl.c_host, NAMELEN);
spcl.c_level = level - '0';
spcl.c_type = TS_TAPE;
msgtail("to %s on host %s\n", tape, host);
else
msgtail("to %s\n", tape);
+ msg("Label: %s\n", labelstr);
#ifdef __linux__
retval = ext2fs_open(disk, 0, 0, 0, unix_io_manager, &fs);
com_err(disk, retval, "while opening filesystem");
if (retval == EXT2_ET_REV_TOO_HIGH)
printf ("Get a newer version of dump!\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
}
if (fs->super->s_rev_level > DUMP_CURRENT_REV) {
com_err(disk, retval, "while opening filesystem");
printf ("Get a newer version of dump!\n");
- exit(X_ABORT);
+ exit(X_STARTUP);
}
if ((diskfd = open(disk, O_RDONLY)) < 0) {
msg("Cannot open %s\n", disk);
- exit(X_ABORT);
+ exit(X_STARTUP);
}
sync();
dev_bsize = DEV_BSIZE;
#else /* __linux __*/
if ((diskfd = open(disk, O_RDONLY)) < 0) {
msg("Cannot open %s\n", disk);
- exit(X_ABORT);
+ exit(X_STARTUP);
}
sync();
sblock = (struct fs *)sblock_buf;
tp_bshift = ffs(TP_BSIZE) - 1;
if (TP_BSIZE != (1 << tp_bshift))
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
- spcl.c_flags |= DR_NEWINODEFMT;
#ifdef FS_44INODEFMT
if (sblock->fs_inodefmt >= FS_44INODEFMT)
spcl.c_flags |= DR_NEWINODEFMT;
anydirskipped = mapdirs(maxino, &tapesize);
}
- if (pipeout) {
+ if (pipeout || unlimited) {
tapesize += 10; /* 10 trailer blocks */
msg("estimated %ld tape blocks.\n", tapesize);
} else {
the end of each block written, and not in mid-block.
Assume no erroneous blocks; this can be compensated
for with an artificially low tape size. */
- fetapes =
- ( tapesize /* blocks */
+ fetapes =
+ ( (double) tapesize /* blocks */
* TP_BSIZE /* bytes/block */
- * (1.0/density) /* 0.1" / byte */
+ * (1.0/density) /* 0.1" / byte " */
+
- tapesize /* blocks */
+ (double) tapesize /* blocks */
* (1.0/ntrec) /* streaming-stops per block */
- * 15.48 /* 0.1" / streaming-stop */
- ) * (1.0 / tsize ); /* tape / 0.1" */
+ * 15.48 /* 0.1" / streaming-stop " */
+ ) * (1.0 / tsize ); /* tape / 0.1" " */
} else {
/* Estimate number of tapes, for old fashioned 9-track
tape */
int tenthsperirg = (density == 625) ? 3 : 7;
fetapes =
- ( tapesize /* blocks */
+ ( (double) tapesize /* blocks */
* TP_BSIZE /* bytes / block */
- * (1.0/density) /* 0.1" / byte */
+ * (1.0/density) /* 0.1" / byte " */
+
- tapesize /* blocks */
+ (double) tapesize /* blocks */
* (1.0/ntrec) /* IRG's / block */
- * tenthsperirg /* 0.1" / IRG */
- ) * (1.0 / tsize ); /* tape / 0.1" */
+ * tenthsperirg /* 0.1" / IRG " */
+ ) * (1.0 / tsize ); /* tape / 0.1" " */
}
etapes = fetapes; /* truncating assignment */
etapes++;
* Allocate tape buffer.
*/
if (!alloctape())
- quit("can't allocate tape buffers - try a smaller blocking factor.\n");
+ quit(
+ "can't allocate tape buffers - try a smaller blocking factor.\n");
startnewtape(1);
(void)time((time_t *)&(tstart_writing));
(void)dumpino(dp, ino);
}
-#ifdef __linux__
(void)time((time_t *)&(tend_writing));
-#endif
spcl.c_type = TS_END;
for (i = 0; i < ntrec; i++)
writeheader(maxino - 1);
if (pipeout)
- msg("DUMP: %ld tape blocks\n",spcl.c_tapea);
+ msg("DUMP: %ld tape blocks\n", spcl.c_tapea);
else
msg("DUMP: %ld tape blocks on %d volumes(s)\n",
spcl.c_tapea, spcl.c_volume);
-#ifdef __linux__
+
/* report dump performance, avoid division through zero */
if (tend_writing - tstart_writing == 0)
msg("finished in less than a second\n");
msg("finished in %d seconds, throughput %d KBytes/sec\n",
tend_writing - tstart_writing,
spcl.c_tapea / (tend_writing - tstart_writing));
-#endif
+
putdumptime();
trewind();
broadcast("DUMP IS DONE!\7\7\n");
msg("DUMP IS DONE\n");
Exit(X_FINOK);
/* NOTREACHED */
+ exit(1); /* gcc - shut up */
}
static void
usage()
{
-
- (void)fprintf(stderr, "usage: dump [-0123456789cnu] [-B records] [-b blocksize] [-d density] [-f file]\n [-h level] [-s feet] [-T date] filesystem\n");
- (void)fprintf(stderr, " dump [-W | -w]\n");
- exit(1);
+ fprintf(stderr,
+ "usage: dump [-0123456789ac"
+#ifdef KERBEROS
+ "k"
+#endif
+ "nu] [-B records] [-b blocksize] [-d density] [-f file]\n"
+ " [-h level] [-s feet] [-T date] filesystem\n"
+ " dump [-W | -w]\n");
+ exit(X_STARTUP);
}
/*
if (dp == NULL)
return (NULL);
*dp = '\0';
- (void)strcpy(rawbuf, cp);
+ (void)strncpy(rawbuf, cp, MAXPATHLEN - 1);
+ rawbuf[MAXPATHLEN-1] = '\0';
*dp = '/';
- (void)strcat(rawbuf, "/r");
- (void)strcat(rawbuf, dp + 1);
+ (void)strncat(rawbuf, "/r", MAXPATHLEN - 1 - strlen(rawbuf));
+ (void)strncat(rawbuf, dp + 1, MAXPATHLEN - 1 - strlen(rawbuf));
return (rawbuf);
#endif /* __linux__ */
}
/*
* obsolete --
- * Change set of key letters and ordered arguments into something
- * getopt(3) will like.
+ * Change set of key letters and ordered arguments into something
+ * getopt(3) will like.
*/
static void
obsolete(argcp, argvp)
char **argvp[];
{
int argc, flags;
- char *ap, **argv, *flagsp, **nargv, *p;
+ char *ap, **argv, *flagsp=NULL, **nargv, *p=NULL;
/* Setup. */
argv = *argvp;
case 's':
case 'T':
if (*argv == NULL) {
- warnx("option requires an argument -- %c", *ap); usage();
+ warnx("option requires an argument -- %c", *ap);
+ usage();
}
if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
err(1, NULL);
}
/* Copy remaining arguments. */
- while (*nargv++ = *argv++);
+ while ((*nargv++ = *argv++));
/* Update argument count. */
*argcp = nargv - *argvp - 1;
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)optr.c 8.2 (Berkeley) 1/6/94";
+#endif
+static const char rcsid[] =
+ "$Id: optr.c,v 1.2 1999/10/11 12:53:22 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <errno.h>
#include <fstab.h>
#include <grp.h>
-#include <signal.h>
#include <stdio.h>
-#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#endif
-#include <tzfile.h>
-#ifdef __STDC__
#include <unistd.h>
-#endif
#include <utmp.h>
-#ifndef __STDC__
-#include <varargs.h>
-#endif
#ifdef __linux__
#include <linux/ext2_fs.h>
#include <ext2fs/ext2fs.h>
#include <bsdcompat.h>
+#include <signal.h>
#endif
#include "dump.h"
/*
* Get the names from the group entry "operator" to notify.
- */
+ */
void
set_operators()
{
sendmes(tty, message)
char *tty, *message;
{
- char t[50], buf[BUFSIZ];
+ char t[MAXPATHLEN], buf[BUFSIZ];
register char *cp;
int lmsg = 1;
FILE *f_tty;
(void) strcpy(t, _PATH_DEV);
- (void) strcat(t, tty);
+ (void) strncat(t, tty, sizeof t - strlen(_PATH_DEV) - 1);
if ((f_tty = fopen(t, "w")) != NULL) {
setbuf(f_tty, buf);
if (tnow >= tschedule) {
tschedule = tnow + 300;
if (blockswritten < 500)
- return;
+ return;
deltat = tstart_writing - tnow +
(1.0 * (tnow - tstart_writing))
/ blockswritten * tapesize;
dt = fstabsearch(dtwalk->dd_name);
dumpme = (dt != NULL &&
dt->fs_freq != 0 &&
- dtwalk->dd_ddate < tnow - (dt->fs_freq * SECSPERDAY));
+ dtwalk->dd_ddate < tnow - (dt->fs_freq * 86400));
if (arg != 'w' || dumpme)
(void) printf(
"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)tape.c 8.4 (Berkeley) 5/1/95";
+#endif
+static const char rcsid[] =
+ "$Id: tape.c,v 1.2 1999/10/11 12:53:22 stelian Exp $";
#endif /* not lint */
+#ifdef __linux__
+#include <sys/types.h>
+#include <linux/types.h>
+#endif
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <ext2fs/ext2fs.h>
#endif
#include "dump.h"
-#include "pathnames.h"
int writesize; /* size of malloc()ed buffer for tape */
long lastspclrec = -1; /* tape block number of last written header */
extern char *host;
char *nexttape;
-static int atomic __P((int (*)(), int, char *, int));
+static int atomic __P((ssize_t (*)(), int, char *, int));
static void doslave __P((int, int));
static void enslave __P((void));
static void flushtape __P((void));
* repositioning after stopping, i.e, streaming mode, where the gap is
* variable, 0.30" to 0.45". The gap is maximal when the tape stops.
*/
- if (blocksperfile == 0)
+ if (blocksperfile == 0 && !unlimited)
tenths = writesize / density +
(cartridge ? 16 : density == 625 ? 5 : 8);
/*
asize += tenths;
blockswritten += ntrec;
blocksthisvol += ntrec;
- if (!pipeout && (blocksperfile ?
+ if (!pipeout && !unlimited && (blocksperfile ?
(blocksthisvol >= blocksperfile) : (asize > tsize))) {
close_rewind();
startnewtape(0);
for (f = 0; f < SLAVES; f++) {
/*
- * Drain the results, but unlike EOT we DO (or should) care
- * what the return values were, since if we detect EOT after
- * we think we've written the last blocks to the tape anyway,
+ * Drain the results, but unlike EOT we DO (or should) care
+ * what the return values were, since if we detect EOT after
+ * we think we've written the last blocks to the tape anyway,
* we have to replay those blocks with rollforward.
*
- * fixme: punt for now.
+ * fixme: punt for now.
*/
if (slaves[f].sent) {
if (atomic(read, slaves[f].fd, (char *)&got, sizeof got)
void
close_rewind()
{
+ time_t tstart_changevol, tend_changevol;
+
trewind();
if (nexttape)
return;
+#ifdef __linux__
+ (void)time4(&(tstart_changevol));
+#else
+ (void)time((time_t *)&(tstart_changevol));
+#endif
if (!nogripe) {
msg("Change Volumes: Mount volume #%d\n", tapeno+1);
broadcast("CHANGE DUMP VOLUMES!\7\7\n");
dumpabort(0);
/*NOTREACHED*/
}
+#ifdef __linux__
+ (void)time4(&(tend_changevol));
+#else
+ (void)time((time_t *)&(tend_changevol));
+#endif
+ if ((tstart_changevol != (time_t)-1) && (tend_changevol != (time_t)-1))
+ tstart_writing += (tend_changevol - tstart_changevol);
}
void
register struct slave *tslp;
int i, size, savedtapea, got;
union u_spcl *ntb, *otb;
+#ifdef __linux__
+ int blks;
+ long lastfirstrec;
+#endif
tslp = &slaves[SLAVES];
ntb = (union u_spcl *)tslp->tblock[1];
/*
- * Each of the N slaves should have requests that need to
- * be replayed on the next tape. Use the extra slave buffers
- * (slaves[SLAVES]) to construct request lists to be sent to
+ * Each of the N slaves should have requests that need to
+ * be replayed on the next tape. Use the extra slave buffers
+ * (slaves[SLAVES]) to construct request lists to be sent to
* each slave in turn.
*/
for (i = 0; i < SLAVES; i++) {
otb = (union u_spcl *)slp->tblock;
/*
- * For each request in the current slave, copy it to tslp.
+ * For each request in the current slave, copy it to tslp.
*/
prev = NULL;
dumpabort(0);
}
slp->sent = 1;
+#ifdef __linux__
+ lastfirstrec = slp->firstrec;
+#endif
if (++slp >= &slaves[SLAVES])
slp = &slaves[0];
if (prev->dblk != 0) {
/*
- * If the last one was a disk block, make the
- * first of this one be the last bit of that disk
+ * If the last one was a disk block, make the
+ * first of this one be the last bit of that disk
* block...
*/
q->dblk = prev->dblk +
ntb = (union u_spcl *)tslp->tblock;
} else {
/*
- * It wasn't a disk block. Copy the data to its
+ * It wasn't a disk block. Copy the data to its
* new location in the buffer.
*/
q->dblk = 0;
slp->req[0] = *q;
nextblock = slp->tblock;
if (q->dblk == 0)
+#ifdef __linux__
+ *(union u_spcl *)(*(nextblock)++) = *(union u_spcl *)tslp->tblock;
+#else
nextblock++;
+#endif
trecno = 1;
/*
quit("EOT detected at start of the tape!\n");
}
}
+
+#ifdef __linux__
+ blks = 0;
+ if (spcl.c_type != TS_END) {
+ for (i = 0; i < spcl.c_count; i++)
+ if (spcl.c_addr[i] != 0)
+ blks++;
+ }
+
+ slp->firstrec = lastfirstrec + ntrec;
+ slp->count = lastspclrec + blks + 1 - spcl.c_tapea;
+ slp->inode = curino;
+ asize += tenths;
+ blockswritten += ntrec;
+ blocksthisvol += ntrec;
+#endif
}
/*
case X_FINOK:
msg("Child %d finishes X_FINOK\n", childpid);
break;
- case X_ABORT:
+ case X_ABORT:
msg("Child %d finishes X_ABORT\n", childpid);
break;
case X_REWRITE:
while ((tapefd = (host ? rmtopen(tape, 2) :
pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
#else
- while ((tapefd = (pipeout ? 1 :
+ while ((tapefd = (pipeout ? 1 :
open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
#endif
{
blocksthisvol = 0;
if (top)
newtape++; /* new tape signal */
- spcl.c_count = slp->count;
+ spcl.c_count = slp->count;
/*
* measure firstrec in TP_BSIZE units since restore doesn't
* know the correct ntrec value...
Exit(X_ABORT);
}
-__dead void
+void
Exit(status)
int status;
{
quit("master/slave protocol botched 4\n");
#endif
- /* write pid of next slave to each slave */
for (i = 0; i < SLAVES; i++)
(void) atomic(write, slaves[i].fd,
(char *) &slaves[(i + 1) % SLAVES].pid,
register int i;
for (i = 0; i < SLAVES; i++)
- if (slaves[i].pid > 0)
+ if (slaves[i].pid > 0) {
(void) kill(slaves[i].pid, SIGKILL);
+ slaves[i].sent = 0;
+ }
}
/*
errcode_t retval;
#endif
-#ifdef TDEBUG
- msg("slave %d, pid %d\n", slave_number, getpid());
-#endif
/*
* Need our own seek pointer.
*/
p->count * TP_BSIZE);
} else {
if (p->count != 1 || atomic(read, cmd,
- (char *)slp->tblock[trecno],
+ (char *)slp->tblock[trecno],
TP_BSIZE) != TP_BSIZE)
quit("master/slave protocol botched.\n");
}
caught = 0;
/* Try to write the data... */
+ wrote = 0;
eot_count = 0;
size = 0;
wrote = write(tapefd, slp->tblock[0]+size,
writesize-size);
#ifdef WRITEDEBUG
- msg("slave %d wrote %d\n", slave_number, wrote);
+ printf("slave %d wrote %d\n", slave_number, wrote);
#endif
- if (wrote < 0)
+ if (wrote < 0)
break;
if (wrote == 0)
eot_count++;
}
#ifdef WRITEDEBUG
- if (size != writesize)
- msg("slave %d only wrote %d out of %d bytes and gave up.\n",
+ if (size != writesize)
+ printf("slave %d only wrote %d out of %d bytes and gave up.\n",
slave_number, size, writesize);
#endif
+ /*
+ * Handle ENOSPC as an EOT condition.
+ */
+ if (wrote < 0 && errno == ENOSPC) {
+ wrote = 0;
+ eot_count++;
+ }
+
if (eot_count > 0)
size = 0;
- /*
- * fixme: Pyramids running OSx return ENOSPC
- * at EOT on 1/2 inch drives.
- */
- if (size < 0) {
+ if (wrote < 0) {
(void) kill(master, SIGUSR1);
for (;;)
(void) sigpause(0);
* (for EOT handling)
*/
(void) atomic(write, cmd, (char *)&size, sizeof size);
- }
+ }
/*
* If partial write, don't want next slave to go.
*/
static int
atomic(func, fd, buf, count)
- int (*func)(), fd;
+ ssize_t (*func)();
+ int fd;
char *buf;
int count;
{
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)traverse.c 8.7 (Berkeley) 6/15/95";
+#endif
+static const char rcsid[] =
+ "$Id: traverse.c,v 1.2 1999/10/11 12:53:22 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
-#include <sys/time.h>
#include <sys/stat.h>
#ifdef __linux__
#include <linux/ext2_fs.h>
#include <bsdcompat.h>
#include <err.h>
#include <stdlib.h>
+#define swab32(x) ext2fs_swab32(x)
#else /* __linux__ */
#ifdef sunos
#include <sys/vnode.h>
typedef long fsizeT;
#endif
-#ifndef __linux__
-static int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size));
-#endif
-static void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size));
#ifdef __linux__
static int searchdir __P((struct ext2_dir_entry *dp, int offset,
int blocksize, char *buf, void *private));
+long long llseek(int fildes, long long offset, int whence);
#else
+static int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size));
+static void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size));
static int searchdir __P((ino_t ino, daddr_t blkno, long size, long filesize));
#endif
long *tapesize;
{
register struct dinode *dp;
- register int i, isdir;
+ register int isdir;
register char *map;
register ino_t ino;
+#ifndef __linux
+ register int i;
long filesize;
+#endif
int ret, change = 0;
isdir = 0; /* XXX just to get gcc to shut up */
isdir >>= 1;
if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap))
continue;
-#ifdef __linux__
dp = getino(ino);
+#ifdef __linux__
ret = 0;
ext2fs_dir_iterate(fs, ino, 0, NULL, searchdir, (void *) &ret);
#else /* __linux__ */
- dp = getino(ino);
filesize = dp->di_size;
for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
if (dp->di_db[i] != 0)
register struct dinode *dp;
ino_t ino;
{
- int ind_level, cnt;
+ int cnt;
fsizeT size;
char buf[TP_BSIZE];
struct old_bsd_inode obi;
#ifdef __linux__
struct block_context bc;
+#else
+ int ind_level;
#endif
if (newtape) {
else
cnt = howmany(dp->di_size, sblock->fs_fsize);
blksout(&dp->di_db[0], cnt, ino);
- if ((size = ((int)dp->di_size) - NDADDR * sblock->fs_bsize) <= 0)
+ if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0)
return;
#ifdef __linux__
bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super);
fsizeT *size;
{
int i, cnt;
+#ifdef __linux__
+ int max;
+ blk_t *swapme;
+#endif
daddr_t idblk[MAXNINDIR];
- if (blk != 0)
+ if (blk != 0) {
bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize);
+#ifdef __linux__
+ /*
+ * My RedHat 4.0 system doesn't have these flags; I haven't
+ * upgraded e2fsprogs yet
+ */
+#if defined(EXT2_FLAG_SWAP_BYTES)
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) {
+#endif
+ max = sblock->fs_bsize >> 2;
+ swapme = (blk_t *) idblk;
+ for (i = 0; i < max; i++, swapme++)
+ *swapme = swab32(*swapme);
+#if defined(EXT2_FLAG_SWAP_BYTES)
+ }
+#endif
+#endif
else
memset(idblk, 0, (int)sblock->fs_bsize);
if (ind_level <= 0) {
#ifdef __linux__
register __s32 sum, cnt, *lp;
#else
- register long sum, cnt, *lp;
+ register int32_t sum, cnt, *lp;
#endif
spcl.c_inumber = ino;
#ifdef __linux__
lp = (__s32 *)&spcl;
#else
- lp = (long *)&spcl;
+ lp = (int32_t *)&spcl;
#endif
sum = 0;
#ifdef __linux__
cnt = sizeof(union u_spcl) / (4 * sizeof(__s32));
#else
- cnt = sizeof(union u_spcl) / (4 * sizeof(long));
+ cnt = sizeof(union u_spcl) / (4 * sizeof(int32_t));
#endif
while (--cnt >= 0) {
sum += *lp++;
* Error recovery is attempted at most BREADEMAX times before seeking
* consent from the operator to continue.
*/
-int breaderrors = 0;
+int breaderrors = 0;
#define BREADEMAX 32
void
bread(blkno, buf, size)
daddr_t blkno;
char *buf;
- int size;
+ int size;
{
int cnt, i;
extern int errno;
loop:
#ifdef __linux__
- if (ext2_llseek(diskfd, ((ext2_loff_t)blkno << dev_bshift), 0) !=
+ if (llseek(diskfd, ((ext2_loff_t)blkno << dev_bshift), 0) !=
((ext2_loff_t)blkno << dev_bshift))
#else
- if ((int)lseek(diskfd, ((off_t)blkno << dev_bshift), 0) == -1)
+ if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) !=
+ ((off_t)blkno << dev_bshift))
#endif
msg("bread: lseek fails\n");
if ((cnt = read(diskfd, buf, size)) == size)
memset(buf, 0, size);
for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) {
#ifdef __linux__
- if (ext2_llseek(diskfd, ((ext2_loff_t)blkno << dev_bshift), 0) !=
+ if (llseek(diskfd, ((ext2_loff_t)blkno << dev_bshift), 0) !=
((ext2_loff_t)blkno << dev_bshift))
#else
- if ((int)lseek(diskfd, ((off_t)blkno << dev_bshift), 0) == -1)
+ if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) !=
+ ((off_t)blkno << dev_bshift))
#endif
msg("bread: lseek2 fails!\n");
if ((cnt = read(diskfd, buf, (int)dev_bsize)) == dev_bsize)
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)unctime.c 8.2 (Berkeley) 6/14/94";
+#endif
+static const char rcsid[] =
+ "$Id: unctime.c,v 1.2 1999/10/11 12:53:23 stelian Exp $";
#endif /* not lint */
-#include <sys/types.h>
-
-#include <stdio.h>
#include <time.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
-#ifndef __P
-#include <sys/cdefs.h>
-#endif
-
/*
* Convert a ctime(3) format string into a system format date.
* Return the date thus calculated.
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)dirs.c 8.7 (Berkeley) 5/1/95";
+#endif
+static const char rcsid[] =
+ "$Id: dirs.c,v 1.2 1999/10/11 12:53:23 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
-#include <sys/time.h>
#ifdef __linux__
#include <linux/ext2_fs.h>
#else /* __linux__ */
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
-#include <ufs/ffs/fs.h>
#endif /* __linux__ */
#include <protocols/dumprestore.h>
+#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
struct inotab {
struct inotab *t_next;
ino_t t_ino;
- long t_seekpt;
- long t_size;
+ int32_t t_seekpt;
+ int32_t t_size;
};
static struct inotab *inotab[HASHSIZE];
#define DIRBLKSIZ 1024
struct rstdirdesc {
int dd_fd;
- long dd_loc;
- long dd_size;
+ int32_t dd_loc;
+ int32_t dd_size;
char dd_buf[DIRBLKSIZ];
};
static long seekpt;
static FILE *df, *mf;
static RST_DIR *dirp;
-static char dirfile[32] = "#"; /* No file */
-static char modefile[32] = "#"; /* No file */
-static char dot[2] = "."; /* So it can be modified */
+static char dirfile[MAXPATHLEN] = "#"; /* No file */
+static char modefile[MAXPATHLEN] = "#"; /* No file */
+static char dot[2] = "."; /* So it can be modified */
/*
* Format of old style directories.
#endif
struct inotab *itp;
struct direct nulldir;
+ int fd;
vprintf(stdout, "Extract directories from tape\n");
- (void) sprintf(dirfile, "%s/rstdir%d", tmpdir, dumpdate);
- df = fopen(dirfile, "w");
- if (df == NULL) {
- fprintf(stderr,
- "restore: %s - cannot create directory temporary\n",
- dirfile);
- fprintf(stderr, "fopen: %s\n", strerror(errno));
+ (void) sprintf(dirfile, "%s/rstdir%ld", tmpdir, dumpdate);
+ if (command != 'r' && command != 'R') {
+ (void *) strcat(dirfile, "-XXXXXX");
+ fd = mkstemp(dirfile);
+ } else
+ fd = open(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666);
+ if (fd == -1 || (df = fdopen(fd, "w")) == NULL) {
+ if (fd != -1)
+ close(fd);
+ warn("%s - cannot create directory temporary\nfopen", dirfile);
done(1);
}
if (genmode != 0) {
- (void) sprintf(modefile, "%s/rstmode%d", tmpdir, dumpdate);
- mf = fopen(modefile, "w");
- if (mf == NULL) {
- fprintf(stderr,
- "restore: %s - cannot create modefile \n",
- modefile);
- fprintf(stderr, "fopen: %s\n", strerror(errno));
+ (void) sprintf(modefile, "%s/rstmode%ld", tmpdir, dumpdate);
+ if (command != 'r' && command != 'R') {
+ (void *) strcat(modefile, "-XXXXXX");
+ fd = mkstemp(modefile);
+ } else
+ fd = open(modefile, O_RDWR|O_CREAT|O_EXCL, 0666);
+ if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) {
+ if (fd != -1)
+ close(fd);
+ warn("%s - cannot create modefile\nfopen", modefile);
done(1);
}
}
nulldir.d_ino = 0;
-#ifdef __linux__
nulldir.d_type = DT_DIR;
-#endif
nulldir.d_namlen = 1;
(void) strcpy(nulldir.d_name, "/");
nulldir.d_reclen = DIRSIZ(0, &nulldir);
}
/*
- * Recursively find names and inumbers of all files in subtree
+ * Recursively find names and inumbers of all files in subtree
* pname and pass them off to be processed.
*/
void
* begin search through the directory
* skipping over "." and ".."
*/
- (void) strncpy(locname, pname, MAXPATHLEN);
- (void) strncat(locname, "/", MAXPATHLEN);
+ (void) strncpy(locname, pname, sizeof(locname) - 1);
+ locname[sizeof(locname) - 1] = '\0';
+ (void) strncat(locname, "/", sizeof(locname) - strlen(locname));
namelen = strlen(locname);
rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
dp = rst_readdir(dirp); /* "." */
*/
while (dp != NULL) {
locname[namelen] = '\0';
- if (namelen + dp->d_namlen >= MAXPATHLEN) {
+ if (namelen + dp->d_namlen >= sizeof(locname)) {
fprintf(stderr, "%s%s: name exceeds %d char\n",
- locname, dp->d_name, MAXPATHLEN);
+ locname, dp->d_name, sizeof(locname) - 1);
} else {
(void) strncat(locname, dp->d_name, (int)dp->d_namlen);
treescan(locname, dp->d_ino, todo);
while (*path == '/')
path++;
dp = NULL;
- while ((name = strsep(&path, "/")) != NULL && *name /* != NULL */) {
+ while ((name = strsep(&path, "/")) != NULL && *name != '\0') {
if ((dp = searchdir(ino, name)) == NULL)
return (NULL);
ino = dp->d_ino;
memset(ndp, 0, (long)(sizeof *ndp));
ndp->d_ino = odp->d_ino;
-#ifdef __linux__
ndp->d_type = DT_UNKNOWN;
-#endif
(void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
ndp->d_namlen = strlen(ndp->d_name);
ndp->d_reclen = DIRSIZ(0, ndp);
return;
loc -= base;
if (loc < 0)
- fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc);
+ fprintf(stderr, "bad seek pointer to rst_seekdir %ld\n", loc);
(void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET);
dirp->dd_loc = loc & (DIRBLKSIZ - 1);
if (dirp->dd_loc != 0)
for (;;) {
if (dirp->dd_loc == 0) {
- dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
+ dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
DIRBLKSIZ);
if (dirp->dd_size <= 0) {
dprintf(stderr, "error reading directory\n");
dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
if (dp->d_reclen == 0 ||
dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
- dprintf(stderr, "corrupted directory: bad reclen %d\n"
- "dd_loc = %d, dd_size = %d\n",
- dp->d_reclen, dirp->dd_loc, dirp->dd_size);
+ dprintf(stderr, "corrupted directory: bad reclen %d\n",
+ dp->d_reclen);
return (NULL);
}
dirp->dd_loc += dp->d_reclen;
struct modeinfo node;
struct entry *ep;
char *cp;
-
+
vprintf(stdout, "Set directory mode, owner, and times.\n");
- (void) sprintf(modefile, "%s/rstmode%d", tmpdir, dumpdate);
+ if (command == 'r' || command == 'R')
+ (void) sprintf(modefile, "%s/rstmode%ld", tmpdir, dumpdate);
+ if (modefile[0] == '#') {
+ panic("modefile not defined\n");
+ fprintf(stderr, "directory mode, owner, and times not set\n");
+ return;
+ }
mf = fopen(modefile, "r");
if (mf == NULL) {
fprintf(stderr, "fopen: %s\n", strerror(errno));
size = i < BUFSIZ ? i : BUFSIZ;
if (read(dp, buf, (int) size) == -1) {
fprintf(stderr,
- "write error extracting inode %d, name %s\n",
+ "write error extracting inode %ld, name %s\n",
curfile.ino, curfile.name);
fprintf(stderr, "read: %s\n", strerror(errno));
done(1);
}
if (!Nflag && write(ofile, buf, (int) size) == -1) {
fprintf(stderr,
- "write error extracting inode %d, name %s\n",
+ "write error extracting inode %ld, name %s\n",
curfile.ino, curfile.name);
fprintf(stderr, "write: %s\n", strerror(errno));
done(1);
/*
* Clean up and exit
*/
-__dead void
+void
done(exitcode)
int exitcode;
{
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
* SUCH DAMAGE.
*
* @(#)extern.h 8.2 (Berkeley) 1/7/94
+ * $Id: extern.h,v 1.2 1999/10/11 12:53:23 stelian Exp $
*/
struct entry *addentry __P((char *, ino_t, int));
long addfile __P((char *, ino_t, int));
+int addwhiteout __P((char *));
void badentry __P((struct entry *, char *));
-void canon __P((char *, char *));
+void canon __P((char *, char *, int));
void checkrestore __P((void));
void closemt __P((void));
+void comparefile __P((char *));
+void compareleaves __P((void));
void createfiles __P((void));
void createleaves __P((char *));
-void compareleaves __P((void));
void createlinks __P((void));
long deletefile __P((char *, ino_t, int));
void deleteino __P((ino_t));
+void delwhiteout __P((struct entry *));
ino_t dirlookup __P((const char *));
__dead void done __P((int));
void dumpsymtable __P((char *, long));
void extractdirs __P((int));
int extractfile __P((char *));
-void comparefile __P((char *));
void findunreflinks __P((void));
char *flagvalues __P((struct entry *));
void freeentry __P((struct entry *));
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)interactive.c 8.5 (Berkeley) 5/1/95";
+#endif
+static const char rcsid[] =
+ "$Id: interactive.c,v 1.2 1999/10/11 12:53:23 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
-#include <sys/time.h>
#include <sys/stat.h>
#ifdef __linux__
#else /* __linux__ */
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
-#include <ufs/ffs/fs.h>
#endif /* __linux__ */
#include <protocols/dumprestore.h>
static char *copynext __P((char *, char *));
static int fcmp __P((const void *, const void *));
static void formatf __P((struct afile *, int));
-static void getcmd __P((char *, char *, char *, struct arglist *));
+static void getcmd __P((char *, char *, char *, int, struct arglist *));
struct dirent *glob_readdir __P((RST_DIR *dirp));
static int glob_stat __P((const char *, struct stat *));
static void mkentry __P((char *, struct direct *, struct afile *));
arglist.glob.gl_closedir = (void *)rst_closedir;
arglist.glob.gl_lstat = glob_stat;
arglist.glob.gl_stat = glob_stat;
- canon("/", curdir);
+ canon("/", curdir, sizeof(curdir));
loop:
if (setjmp(reset) != 0) {
if (arglist.freeglob != 0) {
volno = 0;
}
runshell = 1;
- getcmd(curdir, cmd, name, &arglist);
+ getcmd(curdir, cmd, name, sizeof(name), &arglist);
switch (cmd[0]) {
/*
* Add elements to the extraction list.
* eliminate any embedded ".." components.
*/
static void
-getcmd(curdir, cmd, name, ap)
+getcmd(curdir, cmd, name, size, ap)
char *curdir, *cmd, *name;
struct arglist *ap;
+ int size;
{
register char *cp;
static char input[BUFSIZ];
* If no argument, use curdir as the default.
*/
if (*cp == '\0') {
- (void) strcpy(name, curdir);
+ (void) strncpy(name, curdir, size);
+ name[size - 1] = '\0';
return;
}
nextarg = cp;
* If it is an absolute pathname, canonicalize it and return it.
*/
if (rawname[0] == '/') {
- canon(rawname, name);
+ canon(rawname, name, size);
} else {
/*
* For relative pathnames, prepend the current directory to
* it then canonicalize and return it.
*/
- (void) strcpy(output, curdir);
- (void) strcat(output, "/");
- (void) strcat(output, rawname);
- canon(output, name);
+ snprintf(output, sizeof(output), "%s/%s", curdir, rawname);
+ canon(output, name, size);
}
if (glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob) < 0)
fprintf(stderr, "%s: out of memory\n", ap->cmd);
ap->argcnt = ap->glob.gl_pathc;
retnext:
- strcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt]);
+ strncpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt], size);
+ name[size - 1] = '\0';
if (--ap->argcnt == 0) {
ap->freeglob = 0;
globfree(&ap->glob);
*/
quote = *cp++;
while (*cp != quote && *cp != '\0')
- *bp++ = *cp++ /* | 0200 */;
+ *bp++ = *cp++ | 0200;
if (*cp++ == '\0') {
fprintf(stderr, "missing %c\n", quote);
cp--;
/*
* Canonicalize file names to always start with ``./'' and
- * remove any imbedded "." and ".." components.
+ * remove any embedded "." and ".." components.
*/
void
-canon(rawname, canonname)
+canon(rawname, canonname, len)
char *rawname, *canonname;
+ int len;
{
register char *cp, *np;
(void) strcpy(canonname, ".");
else
(void) strcpy(canonname, "./");
+ if (strlen(canonname) + strlen(rawname) >= len) {
+ fprintf(stderr, "canonname: not enough buffer space\n");
+ done(1);
+ }
+
(void) strcat(canonname, rawname);
/*
* Eliminate multiple and trailing '/'s
char *name;
char *basename;
{
- register struct afile *fp, *list, *listp;
+ register struct afile *fp, *list, *listp=NULL;
register struct direct *dp;
struct afile single;
RST_DIR *dirp;
}
} else {
entries = 0;
-/* while ((dp = rst_readdir(dirp)) && (dp->d_ino != 0)) */
- while (dp = rst_readdir(dirp))
+ while ((dp = rst_readdir(dirp)))
entries++;
rst_closedir(dirp);
list = (struct afile *)malloc(entries * sizeof(struct afile));
(void) strncpy(locname, name, MAXPATHLEN);
(void) strncat(locname, "/", MAXPATHLEN);
namelen = strlen(locname);
- while (dp = rst_readdir(dirp)) {
+ while ((dp = rst_readdir(dirp))) {
if (dp == NULL)
break;
if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)
fp->prefix = '*';
else
fp->prefix = ' ';
-#if 0
- if (inodetype(dp->d_ino) == NODE)
- fp->postfix = '/';
- else
- fp->postfix = ' ';
-#else /* __linux__ */
switch(dp->d_type) {
default:
fp->postfix = ' ';
break;
}
-#endif /* __linux__ */
return;
}
{
register struct afile *fp, *endlist;
int width, bigino, haveprefix, havepostfix;
- int i, j, w, precision, columns, lines;
+ int i, j, w, precision=0, columns, lines;
width = 0;
haveprefix = 0;
for (j = 0; j < columns; j++) {
fp = &list[j * lines + i];
if (vflag) {
- fprintf(stderr, "%*d ", precision, fp->fnum);
+ fprintf(stderr, "%*ld ", precision, fp->fnum);
fp->len += precision + 1;
}
if (haveprefix) {
if (dp == NULL)
return (NULL);
adirent.d_fileno = dp->d_ino;
-#ifdef __linux__
adirent.d_namlen = dp->d_namlen;
-#else
- adirent.d_namlen = dp->d_namlen & 0xff;
-#endif
memmove(adirent.d_name, dp->d_name, dp->d_namlen + 1);
return (&adirent);
}
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
+#endif
+static const char rcsid[] =
+ "$Id: main.c,v 1.2 1999/10/11 12:53:23 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
-#include <sys/time.h>
#include <sys/stat.h>
+#include <errno.h>
#ifdef __linux__
#include <linux/ext2_fs.h>
#include <bsdcompat.h>
+#include <signal.h>
+#include <string.h>
#else /* __linux__ */
#include <ufs/ufs/dinode.h>
-#include <ufs/ffs/fs.h>
#endif /* __linux__ */
#include <protocols/dumprestore.h>
#include <err.h>
-#include <errno.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#ifdef __linux__
int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
int hflag = 1, mflag = 1, Nflag = 0;
+int uflag = 0;
+int dokerberos = 0;
char command = '\0';
long dumpnum = 1;
long volno = 0;
{
int ch;
ino_t ino;
- char *inputdev = _PATH_DEFTAPE;
+ char *inputdev;
char *symtbl = "./restoresymtable";
char *p, name[MAXPATHLEN];
- if (argc < 2)
- usage();
+ /* Temp files should *not* be readable. We set permissions later. */
+ (void) umask(077);
#ifdef __linux__
__progname = argv[0];
#endif
+ if (argc < 2)
+ usage();
+
+ if ((inputdev = getenv("TAPE")) == NULL)
+ inputdev = _PATH_DEFTAPE;
obsolete(&argc, &argv);
- while ((ch = getopt(argc, argv, "b:CcdD:f:himNRrs:tT:vxy")) != EOF)
+#ifdef KERBEROS
+#define optlist "b:CcdDf:hikmNRrs:tTuvxy"
+#else
+#define optlist "b:CcdDf:himNRrs:tTuvxy"
+#endif
+ while ((ch = getopt(argc, argv, optlist)) != -1)
switch(ch) {
case 'b':
/* Change default tape blocksize. */
case 'h':
hflag = 0;
break;
+#ifdef KERBEROS
+ case 'k':
+ dokerberos = 1;
+ break;
+#endif
case 'C':
case 'i':
case 'R':
if (dumpnum <= 0)
errx(1, "dump number must be greater than 0");
break;
+ case 'u':
+ uflag = 1;
+ break;
case 'v':
vflag = 1;
break;
extractdirs(0);
initsymtable((char *)0);
while (argc--) {
- canon(*argv++, name);
+ canon(*argv++, name, sizeof(name));
ino = dirlookup(name);
if (ino == 0)
continue;
extractdirs(1);
initsymtable((char *)0);
while (argc--) {
- canon(*argv++, name);
+ canon(*argv++, name, sizeof(name));
ino = dirlookup(name);
if (ino == 0)
continue;
}
done(0);
/* NOTREACHED */
+ exit(1); /* gcc shut up */
}
static void
usage()
{
(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
- "restore -i [-chmvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -r [-cvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -R [-cvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -x [-chmvy] [-b blocksize] [-f file] [-s fileno] [file ...]", "restore -t [-chvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
+ "restore -i [-chkmuvy] [-b blocksize] [-f file] [-s fileno]",
+ "restore -r [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
+ "restore -R [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
+ "restore -x [-chkmuvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
+ "restore -t [-chkuvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
done(1);
}
char **argvp[];
{
int argc, flags;
- char *ap, **argv, *flagsp, **nargv, *p;
+ char *ap, **argv, *flagsp=NULL, **nargv, *p=NULL;
/* Setup. */
argv = *argvp;
err(1, NULL);
*nargv++ = *argv;
- argv += 2;
+ argv += 2, argc -= 2;
for (flags = 0; *ap; ++ap) {
switch (*ap) {
}
/* Copy remaining arguments. */
- while (*nargv++ = *argv++);
+ while ((*nargv++ = *argv++));
/* Update argument count. */
*argcp = nargv - *argvp - 1;
.\" SUCH DAMAGE.
.\"
.\" @(#)restore.8 8.4 (Berkeley) 5/1/95
+.\" $Id: restore.8,v 1.2 1999/10/11 12:53:24 stelian Exp $
.\"
.Dd May 1, 1995
.Dt RESTORE 8
.Sh SYNOPSIS
.Nm restore
.Fl C
-.Op Fl cvy
+.Op Fl ckvy
.Op Fl b Ar blocksize
.Op Fl D Ar filesystem
.Op Fl f Ar file
.Op Fl T Ar directory
.Nm restore
.Fl i
-.Op Fl chmNvy
+.Op Fl chkmNuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op Fl T Ar directory
.Nm restore
.Fl R
-.Op Fl cNvy
+.Op Fl ckNuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op Fl T Ar directory
.Nm restore
.Fl r
-.Op Fl cNvy
+.Op Fl ckNuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op Fl T Ar directory
.Nm restore
.Fl t
-.Op Fl chvy
+.Op Fl chkNuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op file ...
.Nm restore
.Fl x
-.Op Fl chmNvy
+.Op Fl chkmNuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Fl b
option is not specified,
.Nm restore
-tries to determine the block size dynamically.
+tries to determine the media block size dynamically.
.It Fl c
Normally,
.Nm restore
will try to determine dynamically whether the dump was made from an
-old (pre-4.4) or new format file sytem. The
+old (pre-4.4) or new format file system. The
.Fl c
flag disables this check, and only allows reading a dump in the old
format.
reads from the named file on the remote host using
.Xr rmt 8 .
.Pp
+.It Fl k
+Use Kerberos authentication when contacting the remote tape server.
+(Only available if this options was enabled when
+.Nm restore
+was compiled.)
+.Pp
.It Fl h
Extract the actual directory,
rather than the files that it references.
temporary files. The default value is /tmp. This flag is most useful
when restoring files after having booted from a floppy. There might be little
or no space on the floppy filesystem, but another source of space might exist.
+.It Fl u
+When creating certain types of files, restore may generate a warning
+diagnostic if they already exist in the target directory.
+To prevent this, the
+.Fl u
+(unlink) flag causes restore to remove old entries before attempting
+to create new ones.
.It Fl v
Normally
.Nm restore
may have to resynchronize itself.
This message lists the number of blocks that were skipped over.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TAPE
+If no -f option was specified,
+.Nm
+will use the device specified via
+.Ev TAPE
+as the dump device.
+.Ev TAPE
+may be of the form
+.Qq tapename ,
+.Qq host:tapename ,
+or
+.Qq user@host:tapename .
+.It Ev RMT
+The environment variable
+.Ev RMT
+will be used to determine the pathname of the remote
+.Xr rmt 8
+program.
.Sh FILES
.Bl -tag -width "./restoresymtable" -compact
.It Pa /dev/rmt?
.El
.Sh SEE ALSO
.Xr dump 8 ,
-.Xr newfs 8 ,
.Xr mount 8 ,
+.Xr newfs 8 ,
.Xr mkfs 8 ,
.Xr rmt 8
.Sh BUGS
thus a full dump must be done to get a new set of directories
reflecting the new inode numbering,
even though the contents of the files is unchanged.
+.Pp
+To do a network restore, you have to run restore as root. This is due
+to the previous security history of dump and restore. (restore is
+written to be setuid root, but we are not certain all bugs are gone
+from the restore code - run setuid at your own risk.)
.Sh HISTORY
The
.Nm restore
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
+#endif
+static const char rcsid[] =
+ "$Id: restore.c,v 1.2 1999/10/11 12:53:24 stelian Exp $";
#endif /* not lint */
#include <sys/types.h>
-#include <sys/stat.h>
#ifdef __linux__
#include <sys/time.h>
if (TSTINO(ino, dumpmap) == 0)
return (descend);
vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
- fprintf(stdout, "%10d\t%s\n", ino, name);
+ fprintf(stdout, "%10ld\t%s\n", ino, name);
return (descend);
}
if (ino == WINO && command == 'i' && !vflag)
return (descend);
if (!mflag) {
- (void) sprintf(buf, "./%u", ino);
+ (void) sprintf(buf, "./%lu", ino);
name = buf;
if (type == NODE) {
(void) genliteraldir(name, ino);
return (descend);
}
-/*
+/*
* The following four routines implement the incremental
* restore algorithm. The first removes old entries, the second
* does renames and calculates the extraction list, the third
*
* Directories cannot be immediately deleted, as they may have
* other files in them which need to be moved out first. As
- * directories to be deleted are found, they are put on the
+ * directories to be deleted are found, they are put on the
* following deletion list. After all deletions and renames
* are done, this list is actually deleted.
*/
register ino_t i, mydirino;
vprintf(stdout, "Mark entries to be removed.\n");
- if (ep = lookupino(WINO)) {
+ if ((ep = lookupino(WINO))) {
vprintf(stdout, "Delete whiteouts\n");
for ( ; ep != NULL; ep = nextep) {
nextep = ep->e_links;
# define MODECHG 0x8 /* mode of inode changed */
/*
- * This routine is called once for each element in the
+ * This routine is called once for each element in the
* directory hierarchy, with a full path name.
* The "type" value is incorrectly specified as LEAF for
* directories that are not on the dump tape.
* that we need to rename, so we delete it from the symbol
* table, and put it on the list to be deleted eventually.
* Conversely if a directory is to be created, it must be
- * done immediately, rather than waiting until the
+ * done immediately, rather than waiting until the
* extraction phase.
*/
case ONTAPE|INOFND|MODECHG:
}
if (ip->e_type == LEAF) {
/* changing from leaf to node */
- removeleaf(ip);
- freeentry(ip);
+ for (ip = lookupino(ino); ip != NULL; ip = ip->e_links) {
+ if (ip->e_type != LEAF)
+ badentry(ip, "NODE and LEAF links to same inode");
+ removeleaf(ip);
+ freeentry(ip);
+ }
ip = addentry(name, ino, type);
newnode(ip);
} else {
break;
/*
- * A hard link to a diirectory that has been removed.
+ * A hard link to a directory that has been removed.
* Ignore it.
*/
case NAMEFND:
*/
case NULL:
if (compare_ignore_not_found) break;
- fprintf(stderr, "%s: (inode %d) not found on tape\n",
+ fprintf(stderr, "%s: (inode %ld) not found on tape\n",
name, ino);
break;
default:
panic("[%s] %s: impossible state\n", keyval(key), name);
break;
- }
+ }
return (descend);
}
/* current copy of this file on disk. If do_compare is 0, then just */
/* make our caller think we did it--this is used to handle hard links */
/* to files and devices. */
+void
compare_entry(struct entry *ep, int do_compare)
{
if ((ep->e_flags & (NEW|EXTRACT)) == 0)
* on the next incremental tape.
*/
if (first != curfile.ino) {
- fprintf(stderr, "expected next file %d, got %d\n",
+ fprintf(stderr, "expected next file %ld, got %ld\n",
first, curfile.ino);
skipfile();
goto next;
/*
* If we find files on the tape that have no corresponding
* directory entries, then we must have found a file that
- * was created while the dump was in progress. Since we have
+ * was created while the dump was in progress. Since we have
* no name for it, we discard it knowing that it will be
* on the next incremental tape.
*/
if (first != curfile.ino) {
- fprintf(stderr, "expected next file %d, got %d\n",
+ fprintf(stderr, "expected next file %ld, got %ld\n",
first, curfile.ino);
skipfile();
goto next;
/*
* If the file is to be extracted, then the old file must
* be removed since its type may change from one leaf type
- * to another (eg "file" to "character special").
+ * to another (e.g. "file" to "character special").
*/
if ((ep->e_flags & EXTRACT) != 0) {
removeleaf(ep);
ep->e_flags &= ~(NEW|EXTRACT);
/*
* We checkpoint the restore after every tape reel, so
- * as to simplify the amount of work re quired by the
+ * as to simplify the amount of work required by the
* 'R' command.
*/
next:
register ino_t i;
char name[BUFSIZ];
- if (ep = lookupino(WINO)) {
+ if ((ep = lookupino(WINO))) {
vprintf(stdout, "Add whiteouts\n");
for ( ; ep != NULL; ep = ep->e_links) {
if ((ep->e_flags & NEW) == 0)
ep->e_flags &= ~KEEP;
if (ep->e_type == NODE)
ep->e_flags &= ~(NEW|EXISTED);
- if (ep->e_flags /* != NULL */)
+ if (ep->e_flags != 0)
badentry(ep, "incomplete operations");
}
}
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
extern int hflag; /* restore heirarchies */
extern int mflag; /* restore by name instead of inode number */
extern int Nflag; /* do not write the disk */
+extern int uflag; /* unlink symlink targets */
extern int vflag; /* print out actions taken */
extern int yflag; /* always try to recover from tape errors */
/*
* Global variables
*/
extern char *dumpmap; /* map of inodes on this dump tape */
-extern char *usedinomap; /* map of inodes to be deleted */
+extern char *usedinomap; /* map of inodes that are in use on this fs */
extern ino_t maxino; /* highest numbered inode in this file system */
extern long dumpnum; /* location of the dump on this tape */
extern long volno; /* current volume being read */
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95";
+#endif
+static const char rcsid[] =
+ "$Id: symtab.c,v 1.2 1999/10/11 12:53:24 stelian Exp $";
#endif /* not lint */
/*
cp = name;
for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) {
- for (np = buf; *cp != '/' && *cp != '\0'; )
+ for (np = buf; *cp != '/' && *cp != '\0' &&
+ np < &buf[sizeof(buf)]; )
*np++ = *cp++;
+ if (np == &buf[sizeof(buf)])
+ break;
*np = '\0';
for ( ; ep != NULL; ep = ep->e_sibling)
if (strcmp(ep->e_name, buf) == 0)
}
/*
- * Unused symbol table entries are linked together on a freelist
+ * Unused symbol table entries are linked together on a free list
* headed by the following pointer.
*/
static struct entry *freelist = NULL;
if (type & LINK) {
ep = lookupino(inum);
if (ep == NULL)
- panic("link to non-existant name\n");
+ panic("link to non-existent name\n");
np->e_ino = inum;
np->e_links = ep->e_links;
ep->e_links = np;
/*
* Table of unused string entries, sorted by length.
- *
+ *
* Entries are allocated in STRTBLINCR sized pieces so that names
* of similar lengths can use the same entry. The value of STRTBLINCR
* is chosen so that every entry has at least enough space to hold
* a "struct strtbl" header. Thus every entry can be linked onto an
- * apprpriate free list.
+ * appropriate free list.
*
* NB. The macro "allocsize" below assumes that "struct strhdr"
* has a size that is a power of two.
char *name;
{
struct strhdr *tp, *np;
-
+
tp = &strtblhdr[strlen(name) / STRTBLINCR];
np = (struct strhdr *)name;
np->next = tp->next;
* Useful quantities placed at the end of a dumped symbol table.
*/
struct symtableheader {
- long volno;
- long stringsize;
- long entrytblsize;
+ int32_t volno;
+ int32_t stringsize;
+ int32_t entrytblsize;
time_t dumptime;
time_t dumpdate;
ino_t maxino;
- long ntrec;
+ int32_t ntrec;
};
/*
}
clearerr(fd);
/*
- * Assign indicies to each entry
+ * Assign indices to each entry
* Write out the string entries
*/
- for (i = WINO; i < maxino; i++) {
+ for (i = WINO; i <= maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_index = mynum++;
(void) fwrite(ep->e_name, sizeof(char),
*/
tep = &temp;
stroff = 0;
- for (i = WINO; i < maxino; i++) {
+ for (i = WINO; i <= maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
memmove(tep, ep, (long)sizeof(struct entry));
tep->e_name = (char *)stroff;
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
+#endif
+static const char rcsid[] =
+ "$Id: tape.c,v 1.2 1999/10/11 12:53:24 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/file.h>
-#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/stat.h>
static long fssize = MAXBSIZE;
static int mt = -1;
static int pipein = 0;
-static char magtape[BUFSIZ];
+static char *magtape;
static int blkcnt;
static int numtrec;
static char *tapebuf;
static void xtrmapskip __P((char *, long));
static void xtrskip __P((char *, long));
+static int readmapflag;
+
/*
* Set up an input source
*/
pipein++;
}
setuid(getuid()); /* no longer need or want root privileges */
- (void) strcpy(magtape, source);
+ magtape = strdup(source);
+ if (magtape == NULL) {
+ fprintf(stderr, "Cannot allocate space for magtape buffer\n");
+ done(1);
+ }
}
void
fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
done(1);
}
- if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
+ if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
+ fssize = TP_BSIZE;
+ if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
fssize = stbuf.st_blksize;
if (((fssize - 1) & fssize) != 0) {
- fprintf(stderr, "bad block size %d\n", fssize);
+ fprintf(stderr, "bad block size %ld\n", fssize);
done(1);
}
if (spcl.c_volume != 1) {
done(1);
}
if (gethead(&spcl) == FAIL) {
- dprintf(stdout, "header read failed at %d blocks\n", blksread);
+ dprintf(stdout, "header read failed at %ld blocks\n", blksread);
panic("no header after volume mark!\n");
}
findinode(&spcl);
done(1);
}
maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
- dprintf(stdout, "maxino = %d\n", maxino);
+ dprintf(stdout, "maxino = %ld\n", maxino);
map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
if (map == NULL)
panic("no memory for active inode map\n");
* Prompt user to load a new dump volume.
* "Nextvol" is the next suggested volume to use.
* This suggested volume is enforced when doing full
- * or incremental restores, but can be overrridden by
+ * or incremental restores, but can be overridden by
* the user when only extracting a subset of the files.
*/
void
getvol(nextvol)
long nextvol;
{
- long newvol, savecnt, wantnext, i;
+ long newvol=0, savecnt=0, wantnext=0, i;
union u_spcl tmpspcl;
# define tmpbuf tmpspcl.s_spcl
char buf[TP_BSIZE];
if (command == 'R' || command == 'r' || curfile.action != SKIP) {
newvol = nextvol;
wantnext = 1;
- } else {
+ } else {
newvol = 0;
wantnext = 0;
}
strcpy(buf, ": ");
for (i = 1; i < 32; i++)
if (tapesread & (1 << i)) {
- fprintf(stderr, "%s%d", buf, i);
+ fprintf(stderr, "%s%ld", buf, i);
strcpy(buf, ", ");
}
fprintf(stderr, "\n");
return;
}
closemt();
- fprintf(stderr, "Mount tape volume %d\n", newvol);
+ fprintf(stderr, "Mount tape volume %ld\n", newvol);
fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
(void) fflush(stderr);
setdumpnum();
FLUSHTAPEBUF();
if (gethead(&tmpbuf) == FAIL) {
- dprintf(stdout, "header read failed at %d blocks\n", blksread);
+ dprintf(stdout, "header read failed at %ld blocks\n", blksread);
fprintf(stderr, "tape is not dump tape\n");
volno = 0;
goto again;
* If coming to this volume at random, skip to the beginning
* of the next record.
*/
- dprintf(stdout, "read %ld recs, tape starts with %ld\n",
+ dprintf(stdout, "read %ld recs, tape starts with %d\n",
tpblksread, tmpbuf.c_firstrec);
if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
if (!wantnext) {
* -1 since we've read the volume header
*/
i = tpblksread - tmpbuf.c_firstrec - 1;
- dprintf(stderr, "Skipping %d duplicate record%s.\n",
+ dprintf(stderr, "Skipping %ld duplicate record%s.\n",
i, i > 1 ? "s" : "");
while (--i >= 0)
readtape(buf);
#ifdef RRESTORE
if (host)
rmtioctl(MTFSF, dumpnum - 1);
- else
+ else
#endif
if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
return (linkit(lnkbuf, name, SYMLINK));
#endif
- case IFCHR:
- case IFBLK:
- vprintf(stdout, "extract special file %s\n", name);
+ case IFIFO:
+ vprintf(stdout, "extract fifo %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
- if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
- fprintf(stderr, "%s: cannot create special file: %s\n",
+ if (uflag && !Nflag)
+ (void)unlink(name);
+ if (mkfifo(name, mode) < 0) {
+ fprintf(stderr, "%s: cannot create fifo: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
(void) chmod(name, mode);
-#ifdef __linux__
+#ifdef __linux__
(void) fsetflags(name, flags);
#else
(void) chflags(name, flags);
utimes(name, timep);
return (GOOD);
- case IFIFO:
- vprintf(stdout, "extract fifo %s\n", name);
+ case IFCHR:
+ case IFBLK:
+ vprintf(stdout, "extract special file %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
- if (mkfifo(name, mode) < 0) {
- fprintf(stderr, "%s: cannot create fifo: %s\n",
+ if (uflag)
+ (void)unlink(name);
+ if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
+ fprintf(stderr, "%s: cannot create special file: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
skipfile();
return (GOOD);
}
+ if (uflag)
+ (void)unlink(name);
if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
0666)) < 0) {
fprintf(stderr, "%s: cannot create file: %s\n",
gettingfile++;
loop:
for (i = 0; i < spcl.c_count; i++) {
- if (spcl.c_addr[i]) {
+ if (readmapflag || spcl.c_addr[i]) {
readtape(&buf[curblk++][0]);
if (curblk == fssize / TP_BSIZE) {
(*fill)((char *)buf, (long)(size > TP_BSIZE ?
}
if ((size -= TP_BSIZE) <= 0) {
for (i++; i < spcl.c_count; i++)
- if (spcl.c_addr[i])
+ if (readmapflag || spcl.c_addr[i])
readtape(junk);
break;
}
if (spcl.c_type == TS_ADDR)
goto loop;
dprintf(stdout,
- "Missing address (header) block for %s at %d blocks\n",
+ "Missing address (header) block for %s at %ld blocks\n",
curfile.name, blksread);
}
if (curblk > 0) {
- (*fill)((char *)buf, (curblk * TP_BSIZE) + size);
+ (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
last_write_was_hole = 0;
}
if (last_write_was_hole) {
return;
if (write(ofile, buf, (int) size) == -1) {
fprintf(stderr,
- "write error extracting inode %d, name %s\nwrite: %s\n",
+ "write error extracting inode %ld, name %s\nwrite: %s\n",
curfile.ino, curfile.name, strerror(errno));
done(1);
}
if (lseek(ofile, size, SEEK_CUR) == -1) {
fprintf(stderr,
- "seek error extracting inode %d, name %s\nlseek: %s\n",
+ "seek error extracting inode %ld, name %s\nlseek: %s\n",
curfile.ino, curfile.name, strerror(errno));
done(1);
}
#endif
static char buf_tape[BUFSIZ];
static char buf_disk[BUFSIZ];
- int left = size;
int n_tape;
int n_disk;
if (sbuf_disk->st_size != sbuf_tape.st_size) {
fprintf(stderr,
- "%s: size changed from %d to %d.\n",
+ "%s: size changed from %ld to %ld.\n",
diskfile, sbuf_tape.st_size, sbuf_disk->st_size);
#ifdef COMPARE_FAIL_KEEP_FILE
return (0);
}
curfile.name = name;
+ curfile.action = USING;
mode = curfile.dip->di_mode;
- vprintf(stdout, "comparing %s (size: %d, mode: 0%o)\n", name,
+ vprintf(stdout, "comparing %s (size: %ld, mode: 0%o)\n", name,
sb.st_size, mode);
if (sb.st_mode != mode) {
name,
((int)curfile.dip->di_rdev >> 8) & 0xf,
(int)curfile.dip->di_rdev & 0xf,
- (sb.st_rdev >> 8) & 0xf,
- sb.st_rdev & 0xf);
+ ((int)sb.st_rdev >> 8) & 0xf,
+ (int)sb.st_rdev & 0xf);
}
skipfile();
return;
*/
if (i % TP_BSIZE != 0)
vprintf(stdout,
- "partial block read: %d should be %d\n",
+ "partial block read: %ld should be %ld\n",
i, ntrec * TP_BSIZE);
numtrec = i / TP_BSIZE;
}
fprintf(stderr, "restoring %s\n", curfile.name);
break;
case SKIP:
- fprintf(stderr, "skipping over inode %d\n",
+ fprintf(stderr, "skipping over inode %ld\n",
curfile.ino);
break;
}
done(1);
}
if (i % TP_BSIZE != 0) {
- fprintf(stderr, "Tape block size (%d) %s (%d)\n",
+ fprintf(stderr, "Tape block size (%ld) %s (%d)\n",
i, "is not a multiple of dump block size", TP_BSIZE);
done(1);
}
ntrec = i / TP_BSIZE;
numtrec = ntrec;
- vprintf(stdout, "Tape block size is %d\n", ntrec);
+ vprintf(stdout, "Tape block size is %ld\n", ntrec);
}
void
long i;
union {
quad_t qval;
- long val[2];
+ int32_t val[2];
} qcvt;
union u_ospcl {
char dummy[TP_BSIZE];
struct s_ospcl {
- long c_type;
- long c_date;
- long c_ddate;
- long c_volume;
- long c_tapea;
+ int32_t c_type;
+ int32_t c_date;
+ int32_t c_ddate;
+ int32_t c_volume;
+ int32_t c_tapea;
u_short c_inumber;
- long c_magic;
- long c_checksum;
+ int32_t c_magic;
+ int32_t c_checksum;
struct odinode {
unsigned short odi_mode;
u_short odi_nlink;
u_short odi_uid;
u_short odi_gid;
- long odi_size;
- long odi_rdev;
+ int32_t odi_size;
+ int32_t odi_rdev;
char odi_addr[36];
- long odi_atime;
- long odi_mtime;
- long odi_ctime;
+ int32_t odi_atime;
+ int32_t odi_mtime;
+ int32_t odi_ctime;
} c_dinode;
- long c_count;
+ int32_t c_count;
char c_addr[256];
} s_ospcl;
} u_ospcl;
}
if (checksum((int *)buf) == FAIL)
return (FAIL);
- if (Bcvt)
+ if (Bcvt) {
swabst((u_char *)"8l4s31l", (u_char *)buf);
+ swabst((u_char *)"l",(u_char *) &buf->c_level);
+ swabst((u_char *)"2l",(u_char *) &buf->c_flags);
+ }
goto good;
}
readtape((char *)(&u_ospcl.s_ospcl));
- memset((char *)buf, 0, (long)TP_BSIZE);
+ memset(buf, 0, (long)TP_BSIZE);
buf->c_type = u_ospcl.s_ospcl.c_type;
buf->c_date = u_ospcl.s_ospcl.c_date;
buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
qcvt.val[0] = i;
buf->c_dinode.di_size = qcvt.qval;
}
+ readmapflag = 0;
switch (buf->c_type) {
*/
buf->c_inumber = 0;
buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
- for (i = 0; i < buf->c_count; i++)
- buf->c_addr[i]++;
+ if (buf->c_count > TP_NINDIR)
+ readmapflag = 1;
+ else
+ for (i = 0; i < buf->c_count; i++)
+ buf->c_addr[i]++;
break;
case TS_TAPE:
break;
}
/*
- * If we are restoring a filesystem with old format inodes,
+ * If we are restoring a filesystem with old format inodes,
* copy the uid/gid to the new location.
*/
if (oldinofmt) {
fprintf(stderr, "Used inodes map header");
break;
case TS_INODE:
- fprintf(stderr, "File header, ino %d", previno);
+ fprintf(stderr, "File header, ino %ld", previno);
break;
case TS_ADDR:
- fprintf(stderr, "File continuation header, ino %d", previno);
+ fprintf(stderr, "File continuation header, ino %ld", previno);
break;
case TS_END:
fprintf(stderr, "End of tape header");
break;
}
if (predict != blksread - 1)
- fprintf(stderr, "; predicted %d blocks, got %d blocks",
+ fprintf(stderr, "; predicted %ld blocks, got %ld blocks",
predict, blksread - 1);
fprintf(stderr, "\n");
newcalc:
blks = 0;
if (header->c_type != TS_END)
for (i = 0; i < header->c_count; i++)
- if (header->c_addr[i] != 0)
+ if (readmapflag || header->c_addr[i] != 0)
blks++;
predict = blks;
blksread = 0;
}
} while (header->c_type == TS_ADDR);
if (skipcnt > 0)
- fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
+ fprintf(stderr, "resync restore, skipped %ld blocks\n",
+ skipcnt);
skipcnt = 0;
}
} else {
/* What happens if we want to read restore tapes
for a 16bit int machine??? */
- do
+ do
i += swabl(*buf++);
while (--j);
}
-
+
if (i != CHECKSUM) {
- fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
+ fprintf(stderr, "Checksum error %o, inode %ld file %s\n", i,
curfile.ino, curfile.name);
return(FAIL);
}
case '5': case '6': case '7': case '8': case '9':
n = (n * 10) + (*cp++ - '0');
continue;
-
+
case 's': case 'w': case 'h':
if (n == 0)
n = 1;
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)utilities.c 8.5 (Berkeley) 4/28/95";
+#endif
+static const char rcsid[] =
+ "$Id: utilities.c,v 1.2 1999/10/11 12:53:25 stelian Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct entry *ep;
char *start;
- start = strrchr(name, '/');
+ start = strchr(name, '/');
if (start == 0)
return;
for (cp = start; *cp != '\0'; cp++) {
i++;
if (np == NULL)
badentry(ep, "not on ino list");
- (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
+ (void) sprintf(name, "%s%ld%lu", TMPHDR, i, (u_long)ep->e_ino);
return (name);
}
badentry(np, "newnode: not a node");
cp = myname(np);
if (command == 'C') return;
- if (!Nflag && mkdir(cp, 0777) < 0) {
+
+ if (!Nflag && mkdir(cp, 0777) < 0 && !uflag) {
np->e_flags |= EXISTED;
fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
return;
int type;
{
+ /* if we want to unlink first, do it now so *link() won't fail */
+ if (uflag && !Nflag)
+ (void)unlink(new);
+
if (type == SYMLINK) {
if (!Nflag && symlink(existing, new) < 0) {
fprintf(stderr,
return (FAIL);
}
} else if (type == HARDLINK) {
- if (!Nflag && link(existing, new) < 0) {
- fprintf(stderr,
- "warning: cannot create hard link %s->%s: %s\n",
- new, existing, strerror(errno));
- return (FAIL);
+ int ret;
+
+ if (!Nflag && (ret = link(existing, new)) < 0) {
+
+#ifndef __linux__
+ struct stat s;
+
+ /*
+ * Most likely, the schg flag is set. Clear the
+ * flags and try again.
+ */
+ if (stat(existing, &s) == 0 && s.st_flags != 0 &&
+ chflags(existing, 0) == 0) {
+ ret = link(existing, new);
+ chflags(existing, s.st_flags);
+ }
+#endif
+ if (ret < 0) {
+ fprintf(stderr, "warning: cannot create "
+ "hard link %s->%s: %s\n",
+ new, existing, strerror(errno));
+ return (FAIL);
+ }
}
} else {
panic("linkit: unknown type %d\n", type);
#ifndef __linux__
/*
- * Create a whiteout
+ * Create a whiteout.
*/
int
addwhiteout(name)
"next hashchain name: %s\n", myname(ep->e_next));
fprintf(stderr, "entry type: %s\n",
ep->e_type == NODE ? "NODE" : "LEAF");
- fprintf(stderr, "inode number: %ld\n", ep->e_ino);
+ fprintf(stderr, "inode number: %lu\n", (u_long)ep->e_ino);
panic("flags: %s\n", flagvalues(ep));
}
{
struct direct *dp;
ino_t ino;
-
+
ino = ((dp = pathsearch(name)) == NULL) ? 0 : dp->d_ino;
if (ino == 0 || TSTINO(ino, dumpmap) == 0)
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)rmt.8 8.3 (Berkeley) 12/11/93
+.\" @(#)rmt.8 8.3 (Berkeley) 6/1/94
.\"
.Dd June 1, 1994
.Dt RMT 8
call.
.Pp
The
-.Nm rmt
+.Nm
program accepts requests specific to the manipulation of
magnetic tapes, performs the commands, then responds with
a status indication. All responses are in
.Ar count
exceeds the size of the data buffer (10 kilobytes), it is
truncated to the data buffer size.
-.Nm rmt
+.Nm Rmt
then performs the requested
.Xr read 2
and responds with
.Sm on
.Pp
Any other command causes
-.Nm rmt
+.Nm
to exit.
.Sh DIAGNOSTICS
All responses are of the form described above.
/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999
*
*/
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+#if 0
static char sccsid[] = "@(#)rmt.c 8.1 (Berkeley) 6/6/93";
+#endif
+static const char rcsid[] =
+ "$Id: rmt.c,v 1.2 1999/10/11 12:53:25 stelian Exp $";
#endif /* not lint */
/*
getstring(device);
getstring(mode);
DEBUG2("rmtd: O %s %s\n", device, mode);
- tape = open(device, atoi(mode));
+ /*
+ * XXX the rmt protocol does not provide a means to
+ * specify the permission bits; allow rw for everyone,
+ * as modified by the users umask
+ */
+ tape = open(device, atoi(mode), 0666);
if (tape < 0)
goto ioerror;
goto respond;
goto top;
}
+ case 'V': /* version */
+ getstring(op);
+ DEBUG1("rmtd: V %s\n", op);
+ rval = 2;
+ goto respond;
+
default:
DEBUG1("rmtd: garbage command %c\n", c);
exit(3);
{
DEBUG2("rmtd: E %d (%s)\n", num, strerror(num));
- (void)sprintf(resp, "E%d\n%s\n", num, strerror(num));
+ (void)snprintf(resp, sizeof(resp), "E%d\n%s\n", num, strerror(num));
(void)write(1, resp, strlen(resp));
}