예제 #1
0
/*
 * Determine if given inode should be dumped
 */
void
mapfileino(ino_t ino, int64_t *tapesize, int *dirskipped)
{
	int mode;
	union dinode *dp;

	dp = getino(ino, &mode);
	if (mode == 0)
		return;
	/*
	 * Skip WAPBL log file inodes.
	 */
	if (DIP(dp, di_flags) & SF_LOG)
		return;
	SETINO(ino, usedinomap);
	if (mode == IFDIR)
		SETINO(ino, dumpdirmap);
	if (CHECKNODUMP(dp) &&
	    (DIP(dp, di_mtime) >= spcl.c_ddate ||
	     DIP(dp, di_ctime) >= spcl.c_ddate)) {
		SETINO(ino, dumpinomap);
		if (mode != IFREG && mode != IFDIR && mode != IFLNK)
			*tapesize += 1;
		else
			*tapesize += blockest(dp);
		return;
	}
	if (mode == IFDIR) {
		if (!CHECKNODUMP(dp))
			CLRINO(ino, usedinomap);
		*dirskipped = 1;
	}
}
예제 #2
0
/*
 * Dump pass 2.
 *
 * Scan each directory on the filesystem to see if it has any modified
 * files in it. If it does, and has not already been added to the dump
 * list (because it was itself modified), then add it. If a directory
 * has not been modified itself, contains no modified files and has no
 * subdirectories, then it can be deleted from the dump list and from
 * the list of directories. By deleting it from the list of directories,
 * its parent may now qualify for the same treatment on this or a later
 * pass using this algorithm.
 */
int
mapdirs(ino_t maxino, off_t *tapesize)
{
	union dinode *dp;
	int i, isdir;
	char *map;
	ino_t ino;
	union dinode di;
	off_t filesize;
	int ret, change = 0;

	isdir = 0;		/* XXX just to get gcc to shut up */
	for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
		if (((ino - 1) % NBBY) == 0)	/* map is offset by 1 */
			isdir = *map++;
		else
			isdir >>= 1;
		if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap))
			continue;
		dp = getino(ino, &i);
		/*
		 * inode buf may change in searchdir().
		 */
		if (sblock->fs_magic == FS_UFS1_MAGIC)
			di.dp1 = dp->dp1;
		else
			di.dp2 = dp->dp2;
		filesize = (off_t)DIP(dp, di_size);
		for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
			if (DIP(&di, di_db[i]) != 0)
				ret |= searchdir(ino, DIP(&di, di_db[i]),
				    sblksize(sblock, DIP(dp, di_size), i),
				    filesize);
			if (ret & HASDUMPEDFILE)
				filesize = 0;
			else
				filesize -= sblock->fs_bsize;
		}
		for (i = 0; filesize > 0 && i < NIADDR; i++) {
			if (DIP(&di, di_ib[i]) == 0)
				continue;
			ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize);
		}
		if (ret & HASDUMPEDFILE) {
			SETINO(ino, dumpinomap);
			*tapesize += blockest(dp);
			change = 1;
			continue;
		}
		if ((ret & HASSUBDIRS) == 0) {
			if (!TSTINO(ino, dumpinomap)) {
				CLRINO(ino, dumpdirmap);
				change = 1;
			}
		}
	}
	return (change);
}
예제 #3
0
/*
 * Scan a disk block containing directory information looking to see if
 * any of the entries are on the dump list and to see if the directory
 * contains any subdirectories.
 */
static int
searchdir(ufs1_ino_t ino, daddr_t blkno, long size, long filesize,
          long *tape_size, int nodump)
{
	struct direct *dp;
	struct ufs1_dinode *ip;
	long loc, ret = 0;
	char dblk[MAXBSIZE];

	bread(fsbtodb(sblock, blkno), dblk, (int)size);
	if (filesize < size)
		size = filesize;
	for (loc = 0; loc < size; ) {
		dp = (struct direct *)(dblk + loc);
		if (dp->d_reclen == 0) {
			msg("corrupted directory, inumber %d\n", ino);
			break;
		}
		loc += dp->d_reclen;
		if (dp->d_ino == 0)
			continue;
		if (dp->d_name[0] == '.') {
			if (dp->d_name[1] == '\0')
				continue;
			if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
				continue;
		}
		if (nodump) {
			ip = getino(dp->d_ino);
			if (TSTINO(dp->d_ino, dumpinomap)) {
				CLRINO(dp->d_ino, dumpinomap);
				*tape_size -= blockest(ip);
			}
			/*
			 * Add back to dumpdirmap and remove from usedinomap
			 * to propagate nodump.
			 */
			if ((ip->di_mode & IFMT) == IFDIR) {
				SETINO(dp->d_ino, dumpdirmap);
				CLRINO(dp->d_ino, usedinomap);
				ret |= HASSUBDIRS;
			}
		} else {
			if (TSTINO(dp->d_ino, dumpinomap)) {
				ret |= HASDUMPEDFILE;
				if (ret & HASSUBDIRS)
					break;
			}
			if (TSTINO(dp->d_ino, dumpdirmap)) {
				ret |= HASSUBDIRS;
				if (ret & HASDUMPEDFILE)
					break;
			}
		}
	}
	return (ret);
}
예제 #4
0
/*
 * Dump pass 1.
 *
 * Walk the inode list for a filesystem to find all allocated inodes
 * that have been modified since the previous dump time. Also, find all
 * the directories in the filesystem.
 */
int
mapfiles(ufs1_ino_t maxino, long *tape_size)
{
	int mode;
	ufs1_ino_t ino;
	struct ufs1_dinode *dp;
	int anydirskipped = 0;

	for (ino = ROOTINO; ino < maxino; ino++) {
		dp = getino(ino);
		if ((mode = (dp->di_mode & IFMT)) == 0)
			continue;
		/*
		 * Everything must go in usedinomap so that a check
		 * for "in dumpdirmap but not in usedinomap" to detect
		 * dirs with nodump set has a chance of succeeding
		 * (this is used in mapdirs()).
		 */
		SETINO(ino, usedinomap);
		if (mode == IFDIR)
			SETINO(ino, dumpdirmap);
		if (WANTTODUMP(dp)) {
			SETINO(ino, dumpinomap);
			if (mode != IFREG && mode != IFDIR && mode != IFLNK)
				*tape_size += 1;
			else
				*tape_size += blockest(dp);
			continue;
		}
		if (mode == IFDIR) {
			if (!nonodump && (dp->di_flags & UF_NODUMP))
				CLRINO(ino, usedinomap);
			anydirskipped = 1;
		}
	}
	/*
	 * Restore gets very upset if the root is not dumped,
	 * so ensure that it always is dumped.
	 */
	SETINO(ROOTINO, dumpinomap);
	return (anydirskipped);
}
예제 #5
0
/*
 * Determine if given inode should be dumped
 */
void
mapfileino(ino_t ino, off_t *tapesize, int *dirskipped)
{
	int mode;
	union dinode *dp;

	dp = getino(ino, &mode);
	if (mode == 0)
		return;
	SETINO(ino, usedinomap);
	if (mode == IFDIR)
		SETINO(ino, dumpdirmap);
	if (WANTTODUMP(dp)) {
		SETINO(ino, dumpinomap);
		if (mode != IFREG && mode != IFDIR && mode != IFLNK)
			*tapesize += 1;
		else
			*tapesize += blockest(dp);
		return;
	}
	if (mode == IFDIR)
		*dirskipped = 1;
}
예제 #6
0
파일: tape.c 프로젝트: Alkzndr/freebsd
/*
 * Verify that the tape drive can be accessed and
 * that it actually is a dump tape.
 */
void
setup(void)
{
	int i, j, *ip;
	struct stat stbuf;

	vprintf(stdout, "Verify tape and initialize maps\n");
	if (pipecmdin) {
		if (setenv("RESTORE_VOLUME", "1", 1) == -1) {
			fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
			    strerror(errno));
			done(1);
		}
		popenfp = popen(magtape, "r");
		mt = popenfp ? fileno(popenfp) : -1;
	} else
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
	if (pipein)
		mt = 0;
	else
		mt = open(magtape, O_RDONLY, 0);
	if (mt < 0) {
		fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
		done(1);
	}
	volno = 1;
	setdumpnum();
	FLUSHTAPEBUF();
	if (!pipein && !pipecmdin && !bflag)
		findtapeblksize();
	if (gethead(&spcl) == FAIL) {
		fprintf(stderr, "Tape is not a dump tape\n");
		done(1);
	}
	if (pipein) {
		endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC;
		endoftapemark.s_spcl.c_type = TS_END;
		ip = (int *)&endoftapemark;
		j = sizeof(union u_spcl) / sizeof(int);
		i = 0;
		do
			i += *ip++;
		while (--j);
		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
	}
	if (vflag || command == 't')
		printdumpinfo();
	dumptime = _time64_to_time(spcl.c_ddate);
	dumpdate = _time64_to_time(spcl.c_date);
	if (stat(".", &stbuf) < 0) {
		fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
		done(1);
	}
	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 (((TP_BSIZE - 1) & stbuf.st_blksize) != 0) {
		fprintf(stderr, "Warning: filesystem with non-multiple-of-%d "
		    "blocksize (%d);\n", TP_BSIZE, stbuf.st_blksize);
		fssize = roundup(fssize, TP_BSIZE);
		fprintf(stderr, "\twriting using blocksize %ld\n", fssize);
	}
	if (spcl.c_volume != 1) {
		fprintf(stderr, "Tape is not volume 1 of the dump\n");
		done(1);
	}
	if (gethead(&spcl) == FAIL) {
		dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		panic("no header after volume mark!\n");
	}
	findinode(&spcl);
	if (spcl.c_type != TS_CLRI) {
		fprintf(stderr, "Cannot find file removal list\n");
		done(1);
	}
	maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
	dprintf(stdout, "maxino = %ju\n", (uintmax_t)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, xtrmapskip);
	if (spcl.c_type != TS_BITS) {
		fprintf(stderr, "Cannot find file dump list\n");
		done(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, xtrmapskip);
	/*
	 * If there may be whiteout entries on the tape, pretend that the
	 * whiteout inode exists, so that the whiteout entries can be
	 * extracted.
	 */
	SETINO(WINO, dumpmap);
	/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
	if (command == 'r')
		tapesread = 1;
}
예제 #7
0
/*
 * Scan a disk block containing directory information looking to see if
 * any of the entries are on the dump list and to see if the directory
 * contains any subdirectories.
 */
static int
searchdir(ino_t ino, daddr_t blkno, long size, off_t filesize,
    int64_t *tapesize, int nodump)
{
	struct direct *dp;
	union dinode *ip;
	long loc;
	static caddr_t dblk;
	int mode, ret = 0;

	if (dblk == NULL && (dblk = malloc(sblock->fs_bsize)) == NULL)
		quit("searchdir: cannot allocate indirect memory.\n");
	bread(fsbtodb(sblock, blkno), dblk, (int)size);
	if (filesize < size)
		size = filesize;
	for (loc = 0; loc < size; ) {
		dp = (struct direct *)(dblk + loc);
		if (dp->d_reclen == 0) {
			msg("corrupted directory, inumber %llu\n",
			    (unsigned long long)ino);
			break;
		}
		loc += dp->d_reclen;
		if (dp->d_ino == 0)
			continue;
		if (dp->d_name[0] == '.') {
			if (dp->d_name[1] == '\0')
				continue;
			if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
				continue;
		}
		if (nodump) {
                        ip = getino(dp->d_ino, &mode);
                        if (TSTINO(dp->d_ino, dumpinomap)) {
                                CLRINO(dp->d_ino, dumpinomap);
                                *tapesize -= blockest(ip);
                        }
                        /*
                         * Add back to dumpdirmap and remove from usedinomap
                         * to propagate nodump.
                         */
                        if (mode == IFDIR) {
                                SETINO(dp->d_ino, dumpdirmap);
                                CLRINO(dp->d_ino, usedinomap);
                                ret |= HASSUBDIRS;
                        }
		} else {
			if (TSTINO(dp->d_ino, dumpinomap)) {
				ret |= HASDUMPEDFILE;
				if (ret & HASSUBDIRS)
					break;
			}
			if (TSTINO(dp->d_ino, dumpdirmap)) {
				ret |= HASSUBDIRS;
				if (ret & HASDUMPEDFILE)
					break;
			}
		}
	}
	return (ret);
}
예제 #8
0
/*
 * Dump pass 2.
 *
 * Scan each directory on the filesystem to see if it has any modified
 * files in it. If it does, and has not already been added to the dump
 * list (because it was itself modified), then add it. If a directory
 * has not been modified itself, contains no modified files and has no
 * subdirectories, then it can be deleted from the dump list and from
 * the list of directories. By deleting it from the list of directories,
 * its parent may now qualify for the same treatment on this or a later
 * pass using this algorithm.
 */
int
mapdirs(ino_t maxino, int64_t *tapesize)
{
	union dinode *dp;
	int i, isdir, nodump;
	char *map;
	ino_t ino;
	union dinode di;
	off_t filesize;
	int ret, change = 0;

	isdir = 0;		/* XXX just to get gcc to shut up */
	for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
		if (((ino - 1) % NBBY) == 0)	/* map is offset by 1 */
			isdir = *map++;
		else
			isdir >>= 1;
                /*
		 * If a directory has been removed from usedinomap, it
		 * either has the nodump flag set, or has inherited
		 * it.  Although a directory can't be in dumpinomap if
		 * it isn't in usedinomap, we have to go through it to
		 * propagate the nodump flag.
		 */
		nodump = !nonodump && !TSTINO(ino, usedinomap);
		if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
			continue;
		dp = getino(ino, &i);
		/*
		 * inode buf may change in searchdir().
		 */
		if (sblock->fs_magic == FS_UFS1_MAGIC)
			di.dp1 = dp->dp1;
		else
			di.dp2 = dp->dp2;
		filesize = (off_t)DIP(dp, di_size);
		for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
			if (DIP(&di, di_db[i]) != 0)
				ret |= searchdir(ino, DIP(&di, di_db[i]),
				    sblksize(sblock, DIP(dp, di_size), i),
				    filesize, tapesize, nodump);
			if (ret & HASDUMPEDFILE)
				filesize = 0;
			else
				filesize -= sblock->fs_bsize;
		}
		for (i = 0; filesize > 0 && i < NIADDR; i++) {
			if (DIP(&di, di_ib[i]) == 0)
				continue;
			ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize,
			    tapesize, nodump);
		}
		if (ret & HASDUMPEDFILE) {
			SETINO(ino, dumpinomap);
			*tapesize += blockest(dp);
			change = 1;
			continue;
		}
                if (nodump) {
                        if (ret & HASSUBDIRS)
                                change = 1;     /* subdirs inherit nodump */
                        CLRINO(ino, dumpdirmap);
                } else if ((ret & HASSUBDIRS) == 0) {
			if (!TSTINO(ino, dumpinomap)) {
				CLRINO(ino, dumpdirmap);
				change = 1;
			}
		}
	}
	return (change);
}
예제 #9
0
/*
 * Dump pass 1.
 *
 * Walk the inode list for a filesystem to find all allocated inodes
 * that have been modified since the previous dump time. Also, find all
 * the directories in the filesystem.
 */
int
mapfiles(ino_t maxino, int64_t *tapesize, char *disk, char * const *dirv)
{
	int anydirskipped = 0;

	if (dirv != NULL) {
		char	 curdir[PATH_MAX];
		FTS	*dirh;
		FTSENT	*entry;
		int	 d;

		if (getcwd(curdir, sizeof(curdir)) == NULL) {
			msg("Can't determine cwd: %s\n", strerror(errno));
			dumpabort(0);
		}
		if ((dirh = fts_open(dirv, FTS_PHYSICAL|FTS_SEEDOT|FTS_XDEV,
		    NULL)) == NULL) {
			msg("fts_open failed: %s\n", strerror(errno));
			dumpabort(0);
		}
		while ((entry = fts_read(dirh)) != NULL) {
			switch (entry->fts_info) {
			case FTS_DNR:		/* an error */
			case FTS_ERR:
			case FTS_NS:
				msg("Can't fts_read %s: %s\n", entry->fts_path,
				    strerror(errno));
				/* FALLTHROUGH */
			case FTS_DP:		/* already seen dir */
				continue;
			}
			mapfileino(entry->fts_statp->st_ino, tapesize,
			    &anydirskipped);
		}
		if (errno) {
			msg("fts_read failed: %s\n", strerror(errno));
			dumpabort(0);
		}
		(void)fts_close(dirh);

		/*
		 * Add any parent directories
		 */
		for (d = 0 ; dirv[d] != NULL ; d++) {
			char path[PATH_MAX];

			if (dirv[d][0] != '/')
				(void)snprintf(path, sizeof(path), "%s/%s",
				    curdir, dirv[d]);
			else
				(void)snprintf(path, sizeof(path), "%s",
				    dirv[d]);
			while (strcmp(path, disk) != 0) {
				char *p;
				struct stat sb;

				if (*path == '\0')
					break;
				if ((p = strrchr(path, '/')) == NULL)
					break;
				if (p == path)
					break;
				*p = '\0';
				if (stat(path, &sb) == -1) {
					msg("Can't stat %s: %s\n", path,
					    strerror(errno));
					break;
				}
				mapfileino(sb.st_ino, tapesize, &anydirskipped);
			}
		}

		/*
		 * Ensure that the root inode actually appears in the
		 * file list for a subdir
		 */
		mapfileino(ROOTINO, tapesize, &anydirskipped);
	} else {
		fs_mapinodes(maxino, tapesize, &anydirskipped);
	}
	/*
	 * Restore gets very upset if the root is not dumped,
	 * so ensure that it always is dumped.
	 */
	SETINO(ROOTINO, dumpinomap);
	return (anydirskipped);
}
예제 #10
0
/*
 * Verify that the tape drive can be accessed and
 * that it actually is a dump tape.
 */
void
setup(void)
{
	int i, j, *ip;
	struct stat stbuf;

	vprintf(stdout, "Verify tape and initialize maps\n");
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
	if (pipein)
		mt = 0;
	else
		mt = open(magtape, O_RDONLY, 0);
	if (mt < 0) {
		fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
		done(1);
	}
	volno = 1;
	setdumpnum();
	FLUSHTAPEBUF();
	if (!pipein && !bflag)
		findtapeblksize();
	if (gethead(&spcl) == FAIL) {
		blkcnt--; /* push back this block */
		blksread--;
		cvtflag++;
		if (gethead(&spcl) == FAIL) {
			fprintf(stderr, "Tape is not a dump tape\n");
			done(1);
		}
		fprintf(stderr, "Converting to new file system format.\n");
	}
	if (pipein) {
		endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
		endoftapemark.s_spcl.c_type = TS_END;
		ip = (int *)&endoftapemark;
		j = sizeof(union u_spcl) / sizeof(int);
		i = 0;
		do
			i += *ip++;
		while (--j);
		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
	}
	if (vflag || command == 't')
		printdumpinfo();
	dumptime = spcl.c_ddate;
	dumpdate = spcl.c_date;
	if (stat(".", &stbuf) < 0) {
		fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
		done(1);
	}
	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 %ld\n", fssize);
		done(1);
	}
	if (spcl.c_volume != 1) {
		fprintf(stderr, "Tape is not volume 1 of the dump\n");
		done(1);
	}
	if (gethead(&spcl) == FAIL) {
		dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		panic("no header after volume mark!\n");
	}
	findinode(&spcl);
	if (spcl.c_type != TS_CLRI) {
		fprintf(stderr, "Cannot find file removal list\n");
		done(1);
	}
	maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
	dprintf(stdout, "maxino = %d\n", 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");
		done(1);
	}
	map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for file dump list\n");
	dumpmap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip);
	/*
	 * If there may be whiteout entries on the tape, pretend that the
	 * whiteout inode exists, so that the whiteout entries can be
	 * extracted.
	 */
	if (oldinofmt == 0)
		SETINO(WINO, dumpmap);
	/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
	if (command == 'r')
		tapesread = 1;
}
예제 #11
0
/*
 * Dump pass 2.
 *
 * Scan each directory on the filesystem to see if it has any modified
 * files in it. If it does, and has not already been added to the dump
 * list (because it was itself modified), then add it. If a directory
 * has not been modified itself, contains no modified files and has no
 * subdirectories, then it can be deleted from the dump list and from
 * the list of directories. By deleting it from the list of directories,
 * its parent may now qualify for the same treatment on this or a later
 * pass using this algorithm.
 */
int
mapdirs(ufs1_ino_t maxino, long *tape_size)
{
	struct	ufs1_dinode *dp;
	int isdir, nodump;
	unsigned int i;
	char *map;
	ufs1_ino_t ino;
	struct ufs1_dinode di;
	long filesize;
	int ret, change = 0;

	isdir = 0;		/* XXX just to get gcc to shut up */
	for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
		if (((ino - 1) % NBBY) == 0)	/* map is offset by 1 */
			isdir = *map++;
		else
			isdir >>= 1;
		/*
		 * If a directory has been removed from usedinomap, it
		 * either has the nodump flag set, or has inherited
		 * it.  Although a directory can't be in dumpinomap if
		 * it isn't in usedinomap, we have to go through it to
		 * propagate the nodump flag.
		 */
		nodump = !nonodump && (TSTINO(ino, usedinomap) == 0);
		if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
			continue;
		dp = getino(ino);
		di = *dp;	/* inode buf may change in searchdir(). */
		filesize = di.di_size;
		for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
			if (di.di_db[i] != 0) {
				ret |= searchdir(ino, di.di_db[i],
					(long)dblksize(sblock, &di, i),
					filesize, tape_size, nodump);
			}
			if (ret & HASDUMPEDFILE)
				filesize = 0;
			else
				filesize -= sblock->fs_bsize;
		}
		for (i = 0; filesize > 0 && i < NIADDR; i++) {
			if (di.di_ib[i] == 0)
				continue;
			ret |= dirindir(ino, di.di_ib[i], i, &filesize,
			    tape_size, nodump);
		}
		if (ret & HASDUMPEDFILE) {
			SETINO(ino, dumpinomap);
			*tape_size += blockest(&di);
			change = 1;
			continue;
		}
		if (nodump) {
			if (ret & HASSUBDIRS)
				change = 1;	/* subdirs inherit nodump */
			CLRINO(ino, dumpdirmap);
		} else if ((ret & HASSUBDIRS) == 0)
			if (!TSTINO(ino, dumpinomap)) {
				CLRINO(ino, dumpdirmap);
				change = 1;
			}
	}
	return (change);
}
예제 #12
0
/*
 * Dump pass 1.
 *
 * Walk the inode list for a file system to find all allocated inodes
 * that have been modified since the previous dump time. Also, find all
 * the directories in the file system.
 */
int
mapfiles(ino_t maxino, long *tapesize)
{
	int i, cg, mode, inosused;
	int anydirskipped = 0;
	union dinode *dp;
	struct cg *cgp;
	ino_t ino;
	u_char *cp;

	if ((cgp = malloc(sblock->fs_cgsize)) == NULL)
		quit("mapfiles: cannot allocate memory.\n");
	for (cg = 0; cg < sblock->fs_ncg; cg++) {
		ino = cg * sblock->fs_ipg;
		bread(fsbtodb(sblock, cgtod(sblock, cg)), (char *)cgp,
		    sblock->fs_cgsize);
		if (sblock->fs_magic == FS_UFS2_MAGIC)
			inosused = cgp->cg_initediblk;
		else
			inosused = sblock->fs_ipg;
		/*
		 * If we are using soft updates, then we can trust the
		 * cylinder group inode allocation maps to tell us which
		 * inodes are allocated. We will scan the used inode map
		 * to find the inodes that are really in use, and then
		 * read only those inodes in from disk.
		 */
		if (sblock->fs_flags & FS_DOSOFTDEP) {
			if (!cg_chkmagic(cgp))
				quit("mapfiles: cg %d: bad magic number\n", cg);
			cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
				if (*cp == 0)
					continue;
				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
					if (*cp & i)
						break;
					inosused--;
				}
				break;
			}
			if (inosused <= 0)
				continue;
		}
		for (i = 0; i < inosused; i++, ino++) {
			if (ino < ROOTINO ||
			    (dp = getino(ino, &mode)) == NULL ||
			    (mode & IFMT) == 0)
				continue;
			if (ino >= maxino) {
				msg("Skipping inode %d >= maxino %d\n",
				    ino, maxino);
				continue;
			}
			/*
			 * Everything must go in usedinomap so that a check
			 * for "in dumpdirmap but not in usedinomap" to detect
			 * dirs with nodump set has a chance of succeeding
			 * (this is used in mapdirs()).
			 */
			SETINO(ino, usedinomap);
			if (mode == IFDIR)
				SETINO(ino, dumpdirmap);
			if (WANTTODUMP(dp)) {
				SETINO(ino, dumpinomap);
				if (mode != IFREG &&
				    mode != IFDIR &&
				    mode != IFLNK)
					*tapesize += 1;
				else
					*tapesize += blockest(dp);
				continue;
			}
			if (mode == IFDIR) {
				if (!nonodump &&
				    (DIP(dp, di_flags) & UF_NODUMP))
					CLRINO(ino, usedinomap);
				anydirskipped = 1;
			}
		}
	}
	/*
	 * Restore gets very upset if the root is not dumped,
	 * so ensure that it always is dumped.
	 */
	SETINO(ROOTINO, dumpinomap);
	return (anydirskipped);
}