diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index eb5ce5a1dacc..8e9b5f782225 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -1,4 +1,4 @@ -/* $NetBSD: tape.c,v 1.58 2006/12/18 20:07:32 christos Exp $ */ +/* $NetBSD: tape.c,v 1.59 2007/02/09 09:36:02 hannken Exp $ */ /* * Copyright (c) 1983, 1993 @@ -39,7 +39,7 @@ #if 0 static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; #else -__RCSID("$NetBSD: tape.c,v 1.58 2006/12/18 20:07:32 christos Exp $"); +__RCSID("$NetBSD: tape.c,v 1.59 2007/02/09 09:36:02 hannken Exp $"); #endif #endif /* not lint */ @@ -87,7 +87,6 @@ static const char *host = NULL; #endif static int ofile; -static char *map; static char lnkbuf[MAXPATHLEN + 1]; static int pathlen; @@ -157,6 +156,7 @@ static void accthdr(struct s_spcl *); static int checksum(int *); static void findinode(struct s_spcl *); static void findtapeblksize(void); +static void getbitmap(char **); static int gethead(struct s_spcl *); static void readtape(char *); static void setdumpnum(void); @@ -164,8 +164,6 @@ static void terminateinput(void); static void xtrfile(char *, long); static void xtrlnkfile(char *, long); static void xtrlnkskip(char *, long); -static void xtrmap(char *, long); -static void xtrmapskip(char *, long); static void xtrskip(char *, long); static void swap_header(struct s_spcl *); static void swap_old_header(struct s_ospcl *); @@ -324,24 +322,8 @@ setup(void) fprintf(stderr, "Cannot find file removal list\n"); exit(1); } - maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; - dprintf(stdout, "maxino = %llu\n", (unsigned long long)maxino); - map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); - if (map == NULL) - panic("no memory for active inode map\n"); - usedinomap = map; - curfile.action = USING; - getfile(xtrmap, xtrmapskip); - if (spcl.c_type != TS_BITS) { - fprintf(stderr, "Cannot find file dump list\n"); - exit(1); - } - map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); - if (map == (char *)NULL) - panic("no memory for file dump list\n"); - dumpmap = map; - curfile.action = USING; - getfile(xtrmap, xtrmapskip); + getbitmap(&usedinomap); + getbitmap(&dumpmap); /* * If there may be whiteout entries on the tape, pretend that the * whiteout inode exists, so that the whiteout entries can be @@ -804,6 +786,53 @@ skipfile(void) getfile(xtrnull, xtrnull); } +/* + * Extract a bitmap from the tape. + * The first bitmap sets maxino; + * other bitmaps must be of same size. + */ +void +getbitmap(char **map) +{ + int i; + size_t volatile size = spcl.c_size; + size_t volatile mapsize = size; + char *mapptr; + + curfile.action = USING; + if (spcl.c_type == TS_END) + panic("ran off end of tape\n"); + if (spcl.c_magic != FS_UFS2_MAGIC) + panic("not at beginning of a file\n"); + if (!gettingfile && setjmp(restart) != 0) + return; + gettingfile++; + mapptr = *map = malloc(size); +loop: + if (*map == NULL) + panic("no memory for %s\n", curfile.name); + for (i = 0; i < spcl.c_count && size >= TP_BSIZE; i++) { + readtape(mapptr); + mapptr += TP_BSIZE; + size -= TP_BSIZE; + } + if (size != 0 || i != spcl.c_count) + panic("%s: inconsistent map size\n", curfile.name); + if (gethead(&spcl) == GOOD && spcl.c_type == TS_ADDR) { + size = spcl.c_count * TP_BSIZE; + *map = realloc(*map, mapsize + size); + mapptr = *map + mapsize; + mapsize += size; + goto loop; + } + if (maxino == 0) + maxino = mapsize * NBBY + 1; + else if (maxino != mapsize * NBBY + 1) + panic("%s: map size changed\n", curfile.name); + findinode(&spcl); + gettingfile = 0; +} + /* * Extract a file from the tape. * When an allocated block is found it is passed to the fill function; @@ -833,8 +862,7 @@ getfile(void (*fill)(char *buf, long size), gettingfile++; loop: for (i = 0; i < spcl.c_count; i++) { - if (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI || - spcl.c_addr[i]) { + if (spcl.c_addr[i]) { readtape(&buf[curblk++][0]); if (curblk == fssize / TP_BSIZE) { (*fill)((char *)buf, (long)(size > TP_BSIZE ? @@ -852,21 +880,9 @@ loop: TP_BSIZE : size)); } if ((size -= TP_BSIZE) <= 0) { - if (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) { - /* - * In this case, the following expression - * should always be false since the size was - * initially set to spcl.c_size and - * it is initialized to spcl.c_count * TP_BSIZE - * in gethead(). - */ - if (!(size == 0 && i == spcl.c_count - 1)) - panic("inconsistent map size\n"); - } else { - for (i++; i < spcl.c_count; i++) - if (spcl.c_addr[i]) - readtape(junk); - } + for (i++; i < spcl.c_count; i++) + if (spcl.c_addr[i]) + readtape(junk); break; } } @@ -953,29 +969,6 @@ xtrlnkskip(char *buf __unused, long size __unused) exit(1); } -/* - * Collect the next block of a bit map. - */ -static void -xtrmap(char *buf, long size) -{ - - memmove(map, buf, size); - map += size; -} - -/* - * Skip over a hole in a bit map (should never happen). - */ -/* ARGSUSED */ -static void -xtrmapskip(char *buf __unused, long size) -{ - - panic("hole in map\n"); - map += size; -} - /* * Noop, when an extraction function is not needed. */