home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!news.larc.nasa.gov!teb.larc.nasa.gov!caywood
- From: caywood@teb.larc.nasa.gov (John Caywood)
- Newsgroups: comp.protocols.appletalk
- Subject: Re: Dumping Mac disks to unix hosted tape (long)
- Date: 5 Jan 1993 19:58:27 GMT
- Organization: NASA Langley Research Center, Hampton, VA USA
- Lines: 1251
- Distribution: world
- Message-ID: <1icp93INNoen@rave.larc.nasa.gov>
- References: <1hnmj6INNb8l@rave.larc.nasa.gov>
- NNTP-Posting-Host: teb.larc.nasa.gov
- Keywords: dump backup
-
- In article <1hnmj6INNb8l@rave.larc.nasa.gov>, caywood@teb.larc.nasa.gov (John Caywood) writes:
- |> I'm looking for a Macintosh network backup solution. I have a 150M tape
- |> and a 2.3G tape on a Sun SPARC 2, but no good way to dump Macs to either
- |> tape. I have MacDumper v3.2, but this version only dumps to disk, not
- |> to tape, and has some other limitations. Just checked rutgers.edu and
- |> found that pub/src/macdump.tar.Z is older than the version I have, dating
- |> from (mostly) July, 1989. Got my version from a friend who no longer
- |> works here, so I don't know the source but files are dated Sept. 1990
- |> and Feb. 1991. Is there a newer version somewhere?
- |>
-
- I have two partial solutions so far. Thanks to Steve Faull
- (steve@neopath.wa.com) and Dave Platt (dplatt@ntg.com) for pointing me
- to bbn.com as the source for MacDump. I got the source on 12/29/92 and
- compiled it with only minor problems; used mcvert and capit (from
- cap60/contrib/AufsTools) to convert the Dumper.Hqx and Restore.Hqx
- files from BBN, and it works. The current versions are Dumper 3.3 and
- Restore 2.3.
-
- Dave Platt also sent patches to macdump.c to enable macdump to write
- directly to tape, to verify a dump tape, and to extract the dump file
- back to a UNIX disk. Hence the "partial solution". In Dave's words
-
- There is not, currently, any way to do a "selective" restore from the
- tape dump to Unix disk - you must read back the whole tape, create a
- macrestore-compatible full-dump file, and then restore portions of it to
- the Mac over the network by using Restore. Maybe someday I'll get
- around to adding the ability to extract selected files from the
- tape-dump and write them to Unix disk in CAP/Aufs or AppleSingle or
- MacBinary format.
-
- Dave's dump-to-tape patches work; I've only done a few tests so far, but I
- was able to successfully restore to a Mac files that had been dumped to
- tape with Dave's enhanced macdump. I sent a reply to Dave, but haven't
- heard from him on how we can distribute his patches.
-
- Nigel Gilbert (Nigel.Gilbert@soc.surrey.ac.uk) sent a different partial
- solution. He modified macdump to accept a -directory=folder_name option
- so that you can dump just one folder from a Macintosh volume -- another
- useful feature. It appears that Nigel's modifications are to an earlier
- version of macdump, not the current version at bbn.com, so merging his
- modifications with Dave's is not straightforward. Nigel agreed to let me
- post his modifications, but the file is large and not suitable for posting.
-
- The latest README for the MacDump distribution on bbn.com asserts that no
- further updates will be released by BBN. Judging from the 7 email requests
- I received requesting that I post this summary, there's a clear need for
- these improvements. I have enclosed Dave Platt's patches, plus my own
- patch to the macdump man page documenting the changes, but I prefer not to
- volunteer to maintain the package. Is anyone else willing? Any other
- suggestions on maintaining and distributing these improvements?
-
- Thanks to all who replied.
-
- ==================================================================
- >From dplatt@ntg.com Mon Dec 28 20:13:33 1992
- >From: dplatt@ntg.com (Dave Platt)
- Date: Mon, 28 Dec 1992 17:05:53 PST
- X-Mailer: Mail User's Shell (7.1.1 5/02/90)
- To: caywood@teb.larc.nasa.gov
- Subject: Macintosh dump-to-tape
- Content-Length: 30643
-
- If you apply the following diffs to the most recent version of macdump
- (the one currently on bbn.com) you'll get the ability to dump
- directly from a Mac to tape (bypassing the Unix-disk stage).
-
- The modified macdump accepts the -tape, -read, -verify, and -blocks
- commands. "-tape" means that it should spool the dump session (the
- AppleTalk packet stream, essentially) to standard-output rather than
- writing a disk file. "-read" means that it should read the packet
- stream from standard input and create a dump file which can be processed
- by the macrestore daemon. "-verify" means that it should simply verify
- the input stream rather than creating a dumpfile. "-blocks" specifies
- the number of 512-byte blocks per write to standard-out.
-
- You can dump to tape in either of two ways: direct to the device,
- or via a pipe to "dd". The latter method a bit more complex but
- may give better performance, as it allows dd to be writing one block
- to tape while macdump is filling another block over the network.
-
- For example:
-
- macdump -mac=joe -disk=Big -full -tape -blocks=20 | \
- dd ibs=20b obs=200b of=/dev/rst9
-
- Then, to create a macrestore-compatible file:
-
- dd if=/dev/rst9 ibs=200b obs=20b | \
- macdump -mac=joe -user=joe -read
-
- There is not, currently, any way to do a "selective" restore from the
- tape dump to Unix disk - you must read back the whole tape, create a
- macrestore-compatible full-dump file, and then restore portions of it to
- the Mac over the network by using Restore. Maybe someday I'll get
- around to adding the ability to extract selected files from the
- tape-dump and write them to Unix disk in CAP/Aufs or AppleSingle or
- MacBinary format.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: Makefile.diff macdump.c.diff
- # Wrapped by dplatt@ntg on Mon Dec 28 16:58:12 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile.diff' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.diff'\"
- else
- echo shar: Extracting \"'Makefile.diff'\" \(922 characters\)
- sed "s/^X//" >'Makefile.diff' <<'END_OF_FILE'
- X*** macdump-bbn/Makefile Thu Feb 21 13:12:01 1991
- X--- macdump-merge/Makefile Wed Jun 24 14:15:41 1992
- X***************
- X*** 6,11 ****
- X--- 6,12 ----
- X LIBDIR = /usr/local/lib/cap
- X BINDIR = /usr/local/bin
- X OPERDIR = /usr/ucc/bin
- X+ DUMPFLAGS = -DDOUBLEBUFFER
- X # define this if you want to have a special user that is allowed in with no
- X # password. This if all dumps are stored under a single user name (and if
- X # security is not a problem).
- X***************
- X*** 39,45 ****
- X $(LD) macdump.o print_rec.o $(LDFLAGS)
- X
- X macdump.o: macdump.c macdump.h /usr/include/netat/appletalk.h
- X! $(CC) $(CFLAGS) macdump.c
- X
- X print_rec.o: print_rec.c macdump.h
- X $(CC) $(CFLAGS) print_rec.c
- X--- 40,46 ----
- X $(LD) macdump.o print_rec.o $(LDFLAGS)
- X
- X macdump.o: macdump.c macdump.h /usr/include/netat/appletalk.h
- X! $(CC) $(CFLAGS) $(DUMPFLAGS) macdump.c
- X
- X print_rec.o: print_rec.c macdump.h
- X $(CC) $(CFLAGS) print_rec.c
- END_OF_FILE
- if test 922 -ne `wc -c <'Makefile.diff'`; then
- echo shar: \"'Makefile.diff'\" unpacked with wrong size!
- fi
- # end of 'Makefile.diff'
- fi
- if test -f 'macdump.c.diff' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'macdump.c.diff'\"
- else
- echo shar: Extracting \"'macdump.c.diff'\" \(25771 characters\)
- sed "s/^X//" >'macdump.c.diff' <<'END_OF_FILE'
- X*** macdump-bbn/macdump.c Tue Aug 7 10:51:14 1990
- X--- macdump-merge/macdump.c Fri Aug 21 16:31:36 1992
- X***************
- X*** 42,55 ****
- X--- 42,66 ----
- X
- X /* Definitions */
- X #include <stdio.h>
- X+ #include <malloc.h>
- X #include <sys/types.h>
- X #include <sys/file.h>
- X #include <pwd.h>
- X #include <netat/appletalk.h>
- X #include <time.h>
- X+ #include <sys/time.h>
- X #include <assert.h>
- X #include <sys/stat.h>
- X
- X+ #ifdef DOUBLEBUFFER
- X+ # include <sys/asynch.h>
- X+ # include <unistd.h>
- X+ # include <sys/filio.h>
- X+ # include <fcntl.h>
- X+ # include <signal.h>
- X+ # include <errno.h>
- X+ #endif
- X+
- X #include "macdump.h"
- X #include "dumpprotocol.h"
- X
- X***************
- X*** 67,72 ****
- X--- 78,88 ----
- X int forcefull = 0; /* true to force a full dump */
- X int forceincr = 0; /* true to force an incremental */
- X int getdisknames = 0; /* true to find volume names */
- X+ int tapewrite = 0; /* true if writing to tape rather than disk */
- X+ int taperead = 0; /* true if reading tape */
- X+ int verify = 0;
- X+ int istape = 0;
- X+ time_t timenow;
- X char *progname;
- X AddrBlock macaddr; /* address of macintosh to dump */
- X ABusRecord abr; /* record for remote access */
- X***************
- X*** 90,95 ****
- X--- 106,138 ----
- X char fullname[256];
- X char *dumpname;
- X char tmpname[256];
- X+ char tapeheader[256];
- X+ char magicheader[] = "!macdumptape0";
- X+
- X+ #define BYTESPERBLOCK 512
- X+
- X+ #ifndef TAPEBUFFERSIZE
- X+ # define TAPEBUFFERSIZE 10*BYTESPERBLOCK
- X+ #endif
- X+
- X+ char *tapebuffer;
- X+ int tapebuffersize = TAPEBUFFERSIZE;
- X+ int tapebuffercount;
- X+ int tapebufferavail;
- X+
- X+ #ifdef DOUBLEBUFFER
- X+ char *writebuffer;
- X+ aio_result_t write_result;
- X+ int write_in_progress;
- X+ int write_completed;
- X+ int write_offset;
- X+ int write_trace;
- X+ void wait_for_io();
- X+ extern int aiowrite();
- X+ extern aio_result_t *aiowait();
- X+ #endif
- X+
- X+
- X #define TMPNAME "TMPXXXXXX"
- X
- X #include "dumperrors.h"
- X***************
- X*** 96,101 ****
- X--- 139,147 ----
- X
- X char *CtoPStr(), *PtoCStr();
- X
- X+ void initbuffer();
- X+ void flushbuffer();
- X+
- X main(argc, argv) char **argv;
- X {
- X EntityName en;
- X***************
- X*** 105,110 ****
- X--- 151,157 ----
- X time_t now;
- X struct tm *tmnow, *localtime();
- X int err;
- X+ int i;
- X struct stat fullstatb, incrstatb;
- X char *strcpy();
- X char *p;
- X***************
- X*** 134,139 ****
- X--- 181,208 ----
- X forceincr = 1;
- X else if (strcmp(*argv, "-disknames", 3) == 0)
- X getdisknames = 1;
- X+ else if (strncmp(*argv, "-tape", 5) == 0)
- X+ tapewrite = 1;
- X+ else if (strncmp(*argv, "-read", 5) == 0)
- X+ taperead = 1;
- X+ else if (strncmp(*argv, "-blocks=", 8) == 0) {
- X+ i = atoi(*argv+8);
- X+ if (i > 0 && i <= 9999) {
- X+ tapebuffersize = i * BYTESPERBLOCK;
- X+ } else {
- X+ fprintf(stderr, "%s: blocks must be between 1 and 9999\n", progname);
- X+ clean_exit(EXIT_USER);
- X+ }
- X+ }
- X+ else if (strncmp(*argv, "-verify", 5) == 0) {
- X+ taperead = 1;
- X+ verify = 1;
- X+ }
- X+ #ifdef DOUBLEBUFFER
- X+ else if (strncmp(*argv, "-writetrace", 11) == 0) {
- X+ write_trace = 1;
- X+ }
- X+ #endif
- X else if (strncmp(*argv, "-d", 2) == 0) {
- X ++debug;
- X if (*argv+2 != '\0') dbugarg(*argv+2);
- X***************
- X*** 147,182 ****
- X if (macname == 0)
- X macname = user;
- X
- X if (!getdisknames) {
- X! if (disk == 0 && directory == 0) {
- X fprintf(stderr, "%s: you must specify a disk volume or directory\n",
- X progname);
- X clean_exit(EXIT_USER);
- X }
- X!
- X! if ((pwd = getpwnam(user)) == 0) {
- X! fprintf(stderr, "%s: unknown user %s\n", progname, user);
- X! clean_exit(EXIT_SETUP);
- X }
- X! if (chdir(pwd->pw_dir) < 0) {
- X! fprintf(stderr, "%s: failed to connect to directory %s\n", pwd->pw_dir);
- X! clean_exit(EXIT_SETUP);
- X }
- X- if (chdir("macdumps") < 0) {
- X- fprintf(stderr, "%s: %s has no 'macdumps' directory\n", progname, user);
- X- clean_exit(EXIT_SETUP);
- X- }
- X
- X- /* Run as this user */
- X- setgid(pwd->pw_gid);
- X- setuid(pwd->pw_uid);
- X-
- X- /* Decide whether we are doing a full or an incremental */
- X- strcpy(tmpname, TMPNAME);
- X- mktemp(tmpname); /* temp storage */
- X-
- X }
- X
- X /* Upper case the mac and disk names */
- X for(p = macname; *p; ++p)
- X if (*p >= 'a' && *p <= 'z') *p -= ' ';
- X--- 216,266 ----
- X if (macname == 0)
- X macname = user;
- X
- X+ if (taperead && tapewrite) {
- X+ fprintf(stderr, "Cannot both read and write tape at once!\n");
- X+ clean_exit(EXIT_USER);
- X+ }
- X+
- X+ istape = taperead | tapewrite;
- X+
- X if (!getdisknames) {
- X! if (!verify && (disk == 0 && directory == 0)) {
- X fprintf(stderr, "%s: you must specify a disk volume or directory\n",
- X progname);
- X clean_exit(EXIT_USER);
- X }
- X!
- X! if (!istape) {
- X! if ((pwd = getpwnam(user)) == 0) {
- X! fprintf(stderr, "%s: unknown user %s\n", progname, user);
- X! clean_exit(EXIT_SETUP);
- X! }
- X! if (chdir(pwd->pw_dir) < 0) {
- X! fprintf(stderr, "%s: failed to connect to directory %s\n", pwd->pw_dir);
- X! clean_exit(EXIT_SETUP);
- X! }
- X! if (chdir("macdumps") < 0) {
- X! fprintf(stderr, "%s: %s has no 'macdumps' directory\n", progname, user);
- X! clean_exit(EXIT_SETUP);
- X! }
- X!
- X! /* Run as this user */
- X! setgid(pwd->pw_gid);
- X! setuid(pwd->pw_uid);
- X }
- X!
- X! /* Decide whether we are doing a full or an incremental */
- X! if (verify) {
- X! strcat(tmpname, "/dev/null");
- X! } else {
- X! strcpy(tmpname, TMPNAME);
- X! mktemp(tmpname); /* temp storage */
- X }
- X
- X }
- X
- X+ initbuffer();
- X+
- X /* Upper case the mac and disk names */
- X for(p = macname; *p; ++p)
- X if (*p >= 'a' && *p <= 'z') *p -= ' ';
- X***************
- X*** 223,317 ****
- X full = 0;
- X }
- X
- X! fprintf(stderr, "Doing %s dump to %s\n",
- X! directory == 0 ? (full ? "full" : "incremental") : "directory",
- X! dumpname);
- X }
- X
- X /* Init appletalk */
- X! abInit(debug);
- X!
- X! /* Look up the macintosh */
- X! nbpInit();
- X! strcpy(&en.objStr, macname);
- X! strcpy(&en.typeStr, "DUMPDEV");
- X! strcpy(&en.zoneStr, zone);
- X!
- X! nbpr.nbpRetransmitInfo.retransInterval = 8;
- X! nbpr.nbpRetransmitInfo.retransCount = 20;
- X! nbpr.nbpBufPtr = nbpt;
- X! nbpr.nbpBufSize = sizeof(nbpt);
- X! nbpr.nbpDataField = 1;
- X! nbpr.nbpEntityPtr = &en;
- X! err = NBPLookup(&nbpr, FALSE);
- X! if (err != noErr || nbpr.nbpDataField <= 0) {
- X! fprintf(stderr, "NBP Lookup of %s failed\n", macname);
- X! clean_exit(EXIT_NOMAC);
- X! }
- X! /* Extract the first item */
- X! NBPExtract(nbpt, nbpr.nbpDataField, 1, &en, &macaddr);
- X!
- X! /* No longer need the NBP socket */
- X! nbpShutdown();
- X!
- X! if (debug)
- X printf("Dump device at %d/%d:%02x\n", htons(macaddr.net), macaddr.node,
- X! macaddr.skt);
- X
- X! if (getdisknames) {
- X! int gotname = 0;
- X! register int i;
- X! struct VolNameRecord *vnp;
- X!
- X! for(i = 1; ; ++i) {
- X! register short *ip = (short *)buffer;
- X! *ip = htons(i);
- X!
- X! if (send_cmd(VOLUME_NAME, buffer, sizeof(short)) != ACK) {
- X! if (!gotname)
- X! /* convert response to a C string */
- X! fprintf(stderr, "%s: Response: %s\n", progname, PtoCStr(recbuffer));
- X! break;
- X }
- X! gotname = 1;
- X! vnp = (struct VolNameRecord *)recbuffer;
- X! printf("Volume index %d, disk=\"%s\" %dMB\n", i,
- X! PtoCStr(vnp->volname), htonl(vnp->size)/(1024*1024));
- X }
- X!
- X! /* Have seen all volumes */
- X! clean_exit(EXIT_OK);
- X }
- X
- X! /* Try to access the right disk volume on the mac */
- X! if (directory != 0) {
- X! buffer[0] = strlen(directory);
- X! strcpy(&buffer[1], directory);
- X } else {
- X! buffer[0] = strlen(disk);
- X! strcpy(&buffer[1], disk);
- X }
- X- if (send_cmd(directory == 0 ?
- X- (full ? BEGIN_FULL : BEGIN_INCR) : BEGIN_DIRECTORY,
- X- buffer, buffer[0]+1) != ACK) {
- X- /* convert response to a C string */
- X- fprintf(stderr, "%s: Failed to dump %s. Response: %s\n", progname,
- X- directory == 0 ? disk : directory, PtoCStr(recbuffer));
- X- clean_exit(EXIT_REJECT);
- X- }
- X-
- X- /* If success, open the dump file */
- X- if ((dumpfd = creat(tmpname, 0666)) < 0) {
- X- fprintf(stderr, "%s: Failed to create dump file %s: %s\n",
- X- progname, tmpname, sys_errlist[errno]);
- X- clean_exit(EXIT_SYSTEM);
- X- }
- X- close(dumpfd);
- X- if ((dumpfd = open(tmpname, O_RDWR)) < 0) {
- X- fprintf(stderr, "%s: Failed to re-open dump file %s: %s\n",
- X- progname, tmpname, sys_errlist[errno]);
- X- clean_exit(EXIT_SYSTEM);
- X- }
- X dumpindex = 0; /* start at index 0 */
- X
- X if (directory != 0) {
- X--- 307,431 ----
- X full = 0;
- X }
- X
- X! if (tapewrite) {
- X! fprintf(stderr, "Doing %s dump of %s volume %s to tape\n",
- X! directory == 0 ? (full ? "full" : "incremental") : "directory",
- X! macname, directory != 0 ? directory : disk);
- X! timenow = time(NULL);
- X! sprintf(tapeheader+1, "Dump of %s on %s", dumpname, ctime(&timenow));
- X! tapeheader[0] = strlen(tapeheader+1);
- X! } else if (!taperead) {
- X! fprintf(stderr, "Doing %s dump to %s\n",
- X! directory == 0 ? (full ? "full" : "incremental") : "directory",
- X! dumpname);
- X! }
- X }
- X
- X+ if (taperead) {
- X+ readbytes(stdin, tapeheader, strlen(magicheader));
- X+ if (strcmp(magicheader, tapeheader) != 0) {
- X+ fprintf(stderr, "Bad header: %s\n", tapeheader);
- X+ clean_exit(EXIT_USER);
- X+ }
- X+ readbytes(stdin, tapeheader, 1);
- X+ readbytes(stdin, tapeheader+1, tapeheader[0]);
- X+ fprintf(stderr, "%s", tapeheader+1);
- X+ } else {
- X /* Init appletalk */
- X! abInit(debug);
- X!
- X! /* Look up the macintosh */
- X! nbpInit();
- X! strcpy(&en.objStr, macname);
- X! strcpy(&en.typeStr, "DUMPDEV");
- X! strcpy(&en.zoneStr, zone);
- X!
- X! nbpr.nbpRetransmitInfo.retransInterval = 8;
- X! nbpr.nbpRetransmitInfo.retransCount = 20;
- X! nbpr.nbpBufPtr = nbpt;
- X! nbpr.nbpBufSize = sizeof(nbpt);
- X! nbpr.nbpDataField = 1;
- X! nbpr.nbpEntityPtr = &en;
- X! err = NBPLookup(&nbpr, FALSE);
- X! if (err != noErr || nbpr.nbpDataField <= 0) {
- X! fprintf(stderr, "NBP Lookup of %s failed\n", macname);
- X! clean_exit(EXIT_NOMAC);
- X! }
- X! /* Extract the first item */
- X! NBPExtract(nbpt, nbpr.nbpDataField, 1, &en, &macaddr);
- X!
- X! /* No longer need the NBP socket */
- X! nbpShutdown();
- X!
- X printf("Dump device at %d/%d:%02x\n", htons(macaddr.net), macaddr.node,
- X! macaddr.skt);
- X
- X! if (getdisknames) {
- X! int gotname = 0;
- X! register int i;
- X! struct VolNameRecord *vnp;
- X!
- X! for(i = 1; ; ++i) {
- X! register short *ip = (short *)buffer;
- X! *ip = htons(i);
- X!
- X! if (send_cmd(VOLUME_NAME, buffer, sizeof(short)) != ACK) {
- X! if (!gotname)
- X! /* convert response to a C string */
- X! fprintf(stderr, "%s: Response: %s\n", progname, PtoCStr(recbuffer));
- X! break;
- X! }
- X! gotname = 1;
- X! vnp = (struct VolNameRecord *)recbuffer;
- X! printf("Volume index %d, disk=\"%s\" %dMB\n", i,
- X! PtoCStr(vnp->volname), htonl(vnp->size)/(1024*1024));
- X }
- X! /* Have seen all volumes */
- X! clean_exit(EXIT_OK);
- X }
- X!
- X! /* Try to access the right disk volume on the mac */
- X! if (directory != 0) {
- X! buffer[0] = strlen(directory);
- X! strcpy(&buffer[1], directory);
- X! } else {
- X! buffer[0] = strlen(disk);
- X! strcpy(&buffer[1], disk);
- X! }
- X! if (send_cmd(directory == 0 ?
- X! (full ? BEGIN_FULL : BEGIN_INCR) : BEGIN_DIRECTORY,
- X! buffer, buffer[0]+1) != ACK) {
- X! /* convert response to a C string */
- X! fprintf(stderr, "%s: Failed to dump %s. Response: %s\n", progname,
- X! directory == 0 ? disk : directory, PtoCStr(recbuffer));
- X! clean_exit(EXIT_REJECT);
- X! }
- X }
- X
- X! /* If success, open the dump file or get set for stdout */
- X!
- X! if (tapewrite) {
- X! dumpfd = fileno(stdout);
- X! #ifdef DOUBLEBUFFER
- X! configure_nowait(dumpfd);
- X! #endif
- X! writebytes(dumpfd, magicheader, strlen(magicheader));
- X! writebytes(dumpfd, tapeheader, tapeheader[0]+1);
- X } else {
- X! if (!verify) {
- X! if ((dumpfd = creat(tmpname, 0666)) < 0) {
- X! fprintf(stderr, "%s: Failed to create dump file %s: %s\n",
- X! progname, tmpname, sys_errlist[errno]);
- X! clean_exit(EXIT_SYSTEM);
- X! }
- X! close(dumpfd);
- X! if ((dumpfd = open(tmpname, O_RDWR)) < 0) {
- X! fprintf(stderr, "%s: Failed to re-open dump file %s: %s\n",
- X! progname, tmpname, sys_errlist[errno]);
- X! clean_exit(EXIT_SYSTEM);
- X! }
- X! }
- X }
- X dumpindex = 0; /* start at index 0 */
- X
- X if (directory != 0) {
- X***************
- X*** 342,350 ****
- X clean_exit(EXIT_BADREC);
- X }
- X lastrec.nxtdir = htonl(dumpindex); /* set the link field */
- X! lseek(dumpfd, 0L, 0);
- X! write(dumpfd, &lastrec, htonl(lastrec.reclen));
- X! lseek(dumpfd, dumpindex, L_SET);
- X } else {
- X /* Pull over the records to make the dump */
- X next_record(); /* get the volume record */
- X--- 456,466 ----
- X clean_exit(EXIT_BADREC);
- X }
- X lastrec.nxtdir = htonl(dumpindex); /* set the link field */
- X! if (!tapewrite && !verify) {
- X! lseek(dumpfd, 0L, 0);
- X! write(dumpfd, &lastrec, htonl(lastrec.reclen));
- X! lseek(dumpfd, dumpindex, L_SET);
- X! }
- X } else {
- X /* Pull over the records to make the dump */
- X next_record(); /* get the volume record */
- X***************
- X*** 362,381 ****
- X fprintf(stderr, "%s: Dump of %s failed\n", progname, disk);
- X clean_exit(exitcode);
- X }
- X
- X! /* Set the number of files seen into the volume record */
- X! /* (the MAC only keeps track of files on root) */
- X! set_filecount(dumpfd, totalfiles);
- X }
- X! close(dumpfd);
- X!
- X! /* Rename the temp file to the correct name */
- X! unlink(dumpname);
- X! link(tmpname, dumpname);
- X! unlink(tmpname);
- X! /* If full make sure there is no old incr */
- X! if (full) unlink(incrname);
- X!
- X clean_exit(EXIT_OK);
- X }
- X
- X--- 478,507 ----
- X fprintf(stderr, "%s: Dump of %s failed\n", progname, disk);
- X clean_exit(exitcode);
- X }
- X+
- X+ if (!tapewrite && !verify) {
- X+ /* Set the number of files seen into the volume record */
- X+ /* (the MAC only keeps track of files on root) */
- X+ set_filecount(dumpfd, totalfiles);
- X+ }
- X
- X! if (tapewrite) {
- X! flushbuffer();
- X! #ifdef DOUBLEBUFFER
- X! wait_for_io();
- X! #endif
- X! }
- X!
- X! close(dumpfd);
- X!
- X! /* Rename the temp file to the correct name */
- X! unlink(dumpname);
- X! link(tmpname, dumpname);
- X! unlink(tmpname);
- X! /* If full make sure there is no old incr */
- X! if (full) unlink(incrname);
- X }
- X!
- X clean_exit(EXIT_OK);
- X }
- X
- X***************
- X*** 402,426 ****
- X ++totalfiles; /* a directory counts for our purposes */
- X retval = dumpdir(lastrec.DirID); /* dump this directory recursively */
- X
- X! /* Update the link field in this directory record */
- X! lseek(dumpfd, thisdirrec, L_SET);
- X! if (retval == NAK) return (NAK);
- X! if (read(dumpfd, &lastrec, sizeof(lastrec)) < sizeof(lastrec) - 32) {
- X! fprintf(stderr,
- X! "%s: error re-reading directory record: %s\n",
- X! progname, sys_errlist[errno]);
- X! clean_exit(EXIT_SYSTEM);
- X! } else if ( htonl(lastrec.rectype) != REC_DIR) {
- X! fprintf(stderr,
- X! "%s: error re-reading directory record, got type %d\n",
- X! progname, htonl(lastrec.rectype));
- X! clean_exit(EXIT_SYSTEM);
- X }
- X-
- X- lastrec.nxtdir = htonl(dumpindex); /* set the link field */
- X- lseek(dumpfd, thisdirrec, 0);
- X- write(dumpfd, &lastrec, htonl(lastrec.reclen));
- X- lseek(dumpfd, dumpindex, L_SET);
- X } else if (htonl(lastrec.rectype) == REC_EODIR) {
- X if (lastrec.DirID != thisdirnum) {
- X fprintf(stderr, "%s: wrong directory number in END_OF_DIR record\n",
- X--- 528,554 ----
- X ++totalfiles; /* a directory counts for our purposes */
- X retval = dumpdir(lastrec.DirID); /* dump this directory recursively */
- X
- X! if (!tapewrite && !verify) {
- X! /* Update the link field in this directory record */
- X! lseek(dumpfd, thisdirrec, L_SET);
- X! if (retval == NAK) return (NAK);
- X! if (read(dumpfd, &lastrec, sizeof(lastrec)) < sizeof(lastrec) - 32) {
- X! fprintf(stderr,
- X! "%s: error re-reading directory record: %s\n",
- X! progname, sys_errlist[errno]);
- X! clean_exit(EXIT_SYSTEM);
- X! } else if ( htonl(lastrec.rectype) != REC_DIR) {
- X! fprintf(stderr,
- X! "%s: error re-reading directory record, got type %d\n",
- X! progname, htonl(lastrec.rectype));
- X! clean_exit(EXIT_SYSTEM);
- X! }
- X!
- X! lastrec.nxtdir = htonl(dumpindex); /* set the link field */
- X! lseek(dumpfd, thisdirrec, 0);
- X! write(dumpfd, &lastrec, htonl(lastrec.reclen));
- X! lseek(dumpfd, dumpindex, L_SET);
- X }
- X } else if (htonl(lastrec.rectype) == REC_EODIR) {
- X if (lastrec.DirID != thisdirnum) {
- X fprintf(stderr, "%s: wrong directory number in END_OF_DIR record\n",
- X***************
- X*** 487,518 ****
- X */
- X next_record()
- X {
- X! register int i, j;
- X! register int partial; /* set on partial record received */
- X
- X! /* exitcode set in send_cmd when explicit in this routine */
- X! if (send_cmd(NEXT_RECORD, 0, 0) == NAK) {
- X! printf("NAK: %s\n", PtoCStr(recbuffer));
- X! return(NAK);
- X }
- X- if (debug) print_rec(stdout, recbuffer, 1);
- X
- X /* Save first path of the record */
- X bcopy(recbuffer, &lastrec, sizeof(lastrec));
- X- do {
- X- partial = (((u_char *)&recBDS[0].userData)[0] == PARTIAL);
- X
- X for(i = 0; i < recNBDS; ++i) {
- X dumpindex += recBDS[i].dataSize;
- X! j = recBDS[i].dataSize;
- X! if (write(dumpfd, recBDS[i].buffPtr, j) != j) {
- X! exitcode = EXIT_WRITEFAIL;
- X! return(NAK);
- X }
- X }
- X! if (partial && send_cmd(CONTINUE_RECORD, 0, 0) == NAK) return(NAK);
- X! } while(partial);
- X!
- X return(ACK);
- X }
- X
- X--- 615,711 ----
- X */
- X next_record()
- X {
- X! register int i, j, k;
- X! char partial, moretocome; /* set on partial record received */
- X! register char *p;
- X
- X! if (taperead) {
- X! i = readbytes(stdin, &partial, sizeof partial);
- X! if (i != sizeof partial) return (NAK);
- X! if (partial == -1) return NAK;
- X! i = readbytes(stdin, &recNBDS, sizeof recNBDS);
- X! if (i != sizeof recNBDS) return (NAK);
- X! for(i = 0, p = recbuffer; i < atpMaxNum; ++i, p += atpMaxData) {
- X! recBDS[i].buffPtr = p;
- X! recBDS[i].buffSize = atpMaxData;
- X! }
- X! for (j = 0; j < recNBDS; j++) {
- X! i = readbytes(stdin, &recBDS[j].dataSize, sizeof recBDS[j].dataSize);
- X! if (i != sizeof recBDS[j].dataSize) return (NAK);
- X! i = readbytes(stdin, recBDS[j].buffPtr, recBDS[j].dataSize);
- X! if (i != recBDS[j].dataSize) return (NAK);
- X! if (debug > 1) {
- X! fprintf(stderr, "Read block: %d bytes\n", recBDS[j].dataSize);
- X! }
- X! }
- X! } else {
- X! if (send_cmd(NEXT_RECORD, 0, 0) == NAK) {
- X! printf("NAK: %s\n", PtoCStr(recbuffer));
- X! return(NAK);
- X! }
- X! partial = (((u_char *)&recBDS[0].userData)[0] == PARTIAL);
- X }
- X
- X+ if (debug) print_rec(stderr, recbuffer, 1);
- X+
- X /* Save first path of the record */
- X bcopy(recbuffer, &lastrec, sizeof(lastrec));
- X
- X+ /* Loop through, writing the data to the disk or tape buffer, and
- X+ reading the next segment if the previous read was for a partial
- X+ record.
- X+ */
- X+
- X+ moretocome = 1;
- X+ while (moretocome) {
- X+ moretocome = partial;
- X+ if (debug > 1) {
- X+ fprintf(stderr, "Write record: partial %d, NBDS %d\n", partial, recNBDS);
- X+ }
- X+ if (tapewrite) {
- X+ writebytes(dumpfd, &partial, sizeof partial);
- X+ writebytes(dumpfd, &recNBDS, sizeof recNBDS);
- X+ }
- X for(i = 0; i < recNBDS; ++i) {
- X+ if (tapewrite) {
- X+ writebytes(dumpfd, &recBDS[i].dataSize, sizeof recBDS[i].dataSize);
- X+ writebytes(dumpfd, recBDS[i].buffPtr, recBDS[i].dataSize);
- X+ } else {
- X+ write(dumpfd, recBDS[i].buffPtr, recBDS[i].dataSize);
- X+ }
- X+ if (debug > 1) {
- X+ fprintf(stderr, " Write block: %d bytes at %d\n", recBDS[i].dataSize,
- X+ dumpindex);
- X+ }
- X dumpindex += recBDS[i].dataSize;
- X! }
- X! if (partial) {
- X! if (taperead) {
- X! i = readbytes(stdin, &partial, sizeof partial);
- X! if (i != sizeof partial) return (NAK);
- X! if (partial == -1) return NAK;
- X! i = readbytes(stdin, &recNBDS, sizeof recNBDS);
- X! if (i != sizeof recNBDS) return (NAK);
- X! for (j = 0; j < recNBDS; j++) {
- X! i = readbytes(stdin, &recBDS[j].dataSize,
- X! sizeof recBDS[j].dataSize);
- X! if (i != sizeof recBDS[j].dataSize) return (NAK);
- X! i = readbytes(stdin, recBDS[j].buffPtr, recBDS[j].dataSize);
- X! if (i != recBDS[j].dataSize) return (NAK);
- X! }
- X! } else {
- X! if (send_cmd(CONTINUE_RECORD, 0, 0) == NAK) {
- X! if (tapewrite) {
- X! partial = -1;
- X! writebytes(dumpfd, &partial, sizeof partial);
- X! }
- X! return(NAK);
- X! }
- X! partial = (((u_char *)&recBDS[0].userData)[0] == PARTIAL);
- X }
- X }
- X! }
- X!
- X return(ACK);
- X }
- X
- X***************
- X*** 546,556 ****
- X */
- X clean_exit(code)
- X {
- X! if (tmpname[0]) unlink(tmpname);
- X exit(code);
- X }
- X
- X /*
- X * CtoPStr - C String to Pascal string in place.
- X */
- X char *CtoPStr(p)
- X--- 739,784 ----
- X */
- X clean_exit(code)
- X {
- X! if (tmpname[0] && !verify) unlink(tmpname);
- X exit(code);
- X }
- X
- X /*
- X+ * readbytes - read bytes from a file or socket, guaranteeing that we get
- X+ * as many as we ask for unless EOF occurs. Use the big buffer.
- X+ */
- X+
- X+ int readbytes(theFile, buffer, howMany)
- X+ FILE *theFile;
- X+ char *buffer;
- X+ int howMany;
- X+ {
- X+ int remaining, got, total;
- X+ remaining = howMany;
- X+ total = 0;
- X+ while (remaining > 0) {
- X+ if (tapebufferavail == 0) {
- X+ tapebufferavail = read(fileno(theFile), tapebuffer, tapebuffersize);
- X+ if (tapebufferavail == 0) return total;
- X+ if (tapebufferavail < 0) {
- X+ perror("Error reading from standard input");
- X+ clean_exit(EXIT_SYSTEM);
- X+ }
- X+ tapebuffercount = 0;
- X+ }
- X+ got = tapebufferavail;
- X+ if (got > remaining) got = remaining;
- X+ memcpy(buffer, tapebuffer+tapebuffercount, got);
- X+ total += got;
- X+ buffer += got;
- X+ tapebuffercount += got;
- X+ tapebufferavail -= got;
- X+ remaining -= got;
- X+ }
- X+ return total;
- X+ }
- X+
- X+ /*
- X * CtoPStr - C String to Pascal string in place.
- X */
- X char *CtoPStr(p)
- X***************
- X*** 579,582 ****
- X--- 807,960 ----
- X *p0++ = 0;
- X
- X return(p);
- X+ }
- X+
- X+ void initbuffer()
- X+ {
- X+ int flags;
- X+ tapebuffer = malloc(tapebuffersize);
- X+ if (!tapebuffer) {
- X+ fprintf(stderr, "Could not allocate tape buffer\n");
- X+ clean_exit(EXIT_SYSTEM);
- X+ }
- X+ tapebuffercount = 0;
- X+ tapebufferavail = 0;
- X+ #ifdef DOUBLEBUFFER
- X+ writebuffer = malloc(tapebuffersize);
- X+ if (!writebuffer) {
- X+ fprintf(stderr, "Could not allocate tape buffer\n");
- X+ clean_exit(EXIT_SYSTEM);
- X+ }
- X+ write_in_progress = 0;
- X+ write_offset = 0;
- X+ write_completed = 0;
- X+ #endif
- X+ return;
- X+ }
- X+
- X+
- X+ #ifdef DOUBLEBUFFER
- X+
- X+ int configure_nowait(fd)
- X+ int fd;
- X+ {
- X+ int flags;
- X+ flags = fcntl(fd, F_GETFL, 0);
- X+ if (fcntl(fd, F_SETFL, flags | FNDELAY) == -1) {
- X+ return 0;
- X+ }
- X+ flags = fcntl(fd, F_GETFL, 0);
- X+ if (!(flags & FNDELAY)) {
- X+ fprintf("Failed to set FNDELAY flag!\n");
- X+ return;
- X+ }
- X+ fprintf(stderr, "Successfully configured for asynchronous writes\n");
- X+ }
- X+
- X+ /*
- X+ pushbytes() returns -1 if a "can't write, would block" condition
- X+ exists when it tries to write, and >= 0 otherwise.
- X+ */
- X+
- X+ int pushbytes(fd)
- X+ {
- X+ int result, push;
- X+ if (!write_in_progress) {
- X+ return 0;
- X+ }
- X+ push = tapebuffersize-write_offset;
- X+ if (write_trace) {
- X+ fprintf(stderr, "Writing %d bytes... ", push);
- X+ fflush(stderr);
- X+ }
- X+ result = write(fd, writebuffer+write_offset, push);
- X+ if (result < 0) {
- X+ if (errno != EWOULDBLOCK) {
- X+ perror("Write error");
- X+ clean_exit(EXIT_SYSTEM);
- X+ }
- X+ if (write_trace) {
- X+ fprintf(stderr, "blocked.\n");
- X+ fflush(stderr);
- X+ }
- X+ } else {
- X+ if (write_trace) {
- X+ fprintf(stderr, "wrote %d\n", result);
- X+ fflush(stderr);
- X+ }
- X+ write_offset += result;
- X+ if (write_offset >= tapebuffersize) {
- X+ write_in_progress = 0;
- X+ }
- X+ }
- X+ return result;
- X+ }
- X+
- X+ void wait_for_io(fd)
- X+ int fd;
- X+ {
- X+ int status;
- X+ while (write_in_progress) {
- X+ status = pushbytes(fd);
- X+ if (status == -1) {
- X+ if (write_trace) {
- X+ fprintf(stderr, "Issuing wait\n");
- X+ fflush(stderr);
- X+ }
- X+ sleep(1);
- X+ }
- X+ }
- X+ }
- X+
- X+ #endif
- X+
- X+ void flushbuffer(fd)
- X+ int fd;
- X+ {
- X+ int result;
- X+ if (tapebuffercount > 0) {
- X+ if (tapebuffercount < tapebuffersize) {
- X+ memset(tapebuffer+tapebuffercount, 0, tapebuffersize - tapebuffercount);
- X+ }
- X+ #ifdef DOUBLEBUFFER
- X+ wait_for_io(fd);
- X+ memcpy(writebuffer, tapebuffer, tapebuffersize);
- X+ write_offset = 0;
- X+ write_in_progress = 1;
- X+ pushbytes(fd);
- X+ #else
- X+ if (write(fd, tapebuffer, tapebuffersize) == -1) {
- X+ perror("write() failure");
- X+ clean_exit(EXIT_SYSTEM);
- X+ }
- X+ #endif
- X+ tapebuffercount = 0;
- X+ }
- X+ }
- X+
- X+ int writebytes(fd, data, count)
- X+ int fd;
- X+ char *data;
- X+ int count;
- X+ {
- X+ int now;
- X+ #ifdef DOUBLEBUFFER
- X+ if (write_in_progress) {
- X+ (void) pushbytes(fd);
- X+ }
- X+ #endif
- X+ while (count > 0) {
- X+ if (tapebuffercount == tapebuffersize) {
- X+ flushbuffer(fd);
- X+ }
- X+ now = tapebuffersize - tapebuffercount;
- X+ if (now > count) {
- X+ now = count;
- X+ }
- X+ memcpy(tapebuffer + tapebuffercount, data, now);
- X+ data += now;
- X+ count -= now;
- X+ tapebuffercount += now;
- X+ }
- X+ return 0;
- X }
- END_OF_FILE
- if test 25771 -ne `wc -c <'macdump.c.diff'`; then
- echo shar: \"'macdump.c.diff'\" unpacked with wrong size!
- fi
- # end of 'macdump.c.diff'
- fi
- echo shar: End of shell archive.
- exit 0
-
- ==============================================================
- # This is a shell archive. Save it in a file, remove anything before
- # this line, and then unpack it by entering "sh file". Note, it may
- # create directories; files and directories will be owned by you and
- # have default permissions.
- #
- # This archive contains:
- #
- # macdump.man.diff
- #
- echo x - macdump.man.diff
- sed 's/^X//' >macdump.man.diff << 'END-of-macdump.man.diff'
- X*** macdump-merge/macdump.8 Tue Jan 10 11:52:18 1989
- X--- macdump-bbn/macdump.8 Tue Dec 29 14:54:08 1992
- X***************
- X*** 3,14 ****
- X macdump - perform an automated backup of a Macintosh
- X .SH SYNTAX
- X .B macdump
- X! \-user=name \-disk=name [ \-mac=name ] [ \-zone=name ] [ \-full ] [ \-incr ] [ \-debug ] [ \-disknames ]
- X .SH DESCRIPTION
- X .I macdump
- X is run to perform a backup operation of a Macintosh on Appletalk.
- X The Macintosh must be running the network dump server.
- X .PP
- X The
- X .B \-user=
- X parameter specifies the user name that the dump files will be owned by.
- X--- 3,24 ----
- X macdump - perform an automated backup of a Macintosh
- X .SH SYNTAX
- X .B macdump
- X! \-user=name \-disk=name [ \-mac=name ] [ \-zone=name ] [ \-full ] [ \-incr ] [ \-debug ] [ \-disknames ] [ \-tape ] [ \-read ] [ \-blocks=n ] [ \-verify ] [ \-writetrace ]
- X .SH DESCRIPTION
- X .I macdump
- X is run to perform a backup operation of a Macintosh on Appletalk.
- X The Macintosh must be running the network dump server.
- X+ If the
- X+ .B \-tape
- X+ option is specified, the dump image is written to the standard output
- X+ (which may be redirected to a tape device);
- X+ otherwise the image will be written to a dumpfile.
- X .PP
- X+ There is not, currently, any way to do a "selective" restore from the
- X+ tape dump to Unix disk \(em you must read back the whole tape, create a
- X+ \fImacrestore\fP\^-compatible full-dump file, and then restore portions of it to
- X+ the Mac over the network by using Restore.
- X+ .PP
- X The
- X .B \-user=
- X parameter specifies the user name that the dump files will be owned by.
- X***************
- X*** 45,50 ****
- X--- 55,159 ----
- X options when using the
- X .B \-diskname
- X option.
- X+ .PP
- X+ The
- X+ .B \-tape
- X+ option instructs
- X+ .I macdump
- X+ to write the dump image to the standard output;
- X+ if the command line redirects this to a tape device, the dump image will
- X+ be written directly to tape instead of to a disk file.
- X+ .PP
- X+ The
- X+ .B \-read
- X+ option instructs
- X+ .I macdump
- X+ to read from the standard input, which is typically redirected to a tape device,
- X+ and create a dump file that is compatible with the
- X+ .I macrestore
- X+ program.
- X+ If both the
- X+ .B \-tape
- X+ and
- X+ .B \-read
- X+ options are present, the program exits with an error indication.
- X+ .PP
- X+ .B \-verify
- X+ presumes the
- X+ .B \-read
- X+ option, but no dump file is written;
- X+ when an execution of
- X+ .I macdump
- X+ .B \-tape
- X+ is followed by
- X+ .I macdump
- X+ .B \-verify
- X+ the program verifies that all data on the tape is readable.
- X+ It
- X+ .I "does not"
- X+ verify the data on the tape against the data on the Macintosh.
- X+ .PP
- X+ .B \-blocks=
- X+ specifies the number of 512-byte blocks to read or write when using tape;
- X+ the default is 10 blocks.
- X+ Specifying less than 1 block or more than 9999 blocks will cause
- X+ .I macdump
- X+ to exit with an error indication.
- X+ .PP
- X+ The
- X+ .B \-writetrace
- X+ option provides additional debugging for tape operation.
- X+ .SH EXAMPLES
- X+ .PP
- X+ Execute
- X+ .I macdump
- X+ with these options to dump the disk
- X+ .B "Macintosh HD"
- X+ on a Macintosh named
- X+ .I Joe
- X+ to a disk file in the home directory of user
- X+ .I oper.
- X+ .IP
- X+ .B
- X+ macdump -user=oper -disk="Macintosh HD" -mac=Joe -full
- X+ .PP
- X+ The same disk can be dumped to tape in either of two ways:
- X+ direct to the device, or via a pipe to
- X+ .I dd.
- X+ The latter method a bit more complex but
- X+ may give better performance, as it allows
- X+ .I dd
- X+ to be writing one block
- X+ to tape while
- X+ .I macdump
- X+ is filling another block over the network.
- X+ To use the QIC-150 tapedrive
- X+ .I rst0,
- X+ .IP
- X+ .B
- X+ macdump -disk="Macintosh HD" -mac=Joe -full -tape -blocks=20 > /dev/rst0
- X+ .PP
- X+ or
- X+ .IP
- X+ .B
- X+ macdump -disk="Macintosh HD" -mac=Joe -full -tape -blocks=20 | \\
- X+ .IP
- X+ .B
- X+ dd ibs=20b obs=200b of=/dev/rst0
- X+ .PP
- X+ To verify that dump
- X+ .IP
- X+ .B
- X+ macdump -disk="Macintosh HD" -mac=Joe -verify -blocks=20 < /dev/rst0
- X+ .PP
- X+ To create a disk dump file for use by
- X+ .I macrestore,
- X+ .IP
- X+ .B
- X+ dd if=/dev/rst0 ibs=200b obs=20b | macdump -disk="Macintosh HD" -mac=Joe -read
- X+ .PP
- X+ Note the use of double quotes to preserve the spaces in the hard disk
- X+ volume name in these examples.
- X .SH SEE ALSO
- X macrestore(8), macdumpdir(8)
- X
- END-of-macdump.man.diff
- exit
-
-