Add support for Solaris ufsdump volumes with more than 512*1024 inodes.

Here the bitmaps are written as

	CLRI or BITS with c_count <= 512
	ADDR* for the remaining blocks

Remove the bitmap handling from getfile(), remove xtrmap() and xtrmapskip().
Add new function getbitmap() modeled after getfile() that does bitmap
allocation, bitmap expansion and sets maxino.

Reviewed by: Manuel Bouyer <bouyer@netbsd.org>
This commit is contained in:
hannken 2007-02-09 09:36:02 +00:00
parent b2668f252f
commit f67846b19f
1 changed files with 56 additions and 63 deletions

View File

@ -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.
*/