예제 #1
0
void
bread(daddr_t blkno, char *buf, int size)
{
	int cnt, i;

loop:
	cnt = cread(diskfd, buf, size, ((off_t)blkno << dev_bshift));
	if (cnt == size)
		return;
	if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {
		/*
		 * Trying to read the final fragment.
		 *
		 * NB - dump only works in TP_BSIZE blocks, hence
		 * rounds `dev_bsize' fragments up to TP_BSIZE pieces.
		 * It should be smarter about not actually trying to
		 * read more than it can get, but for the time being
		 * we punt and scale back the read only when it gets
		 * us into trouble. (mkm 9/25/83)
		 */
		size -= dev_bsize;
		goto loop;
	}
	if (cnt == -1)
		msg("read error from %s: %s: [block %d]: count=%d\n",
			disk, strerror(errno), blkno, size);
	else
		msg("short read error from %s: [block %d]: count=%d, got=%d\n",
			disk, blkno, size, cnt);
	if (++breaderrors > BREADEMAX) {
		msg("More than %d block read errors from %s\n",
			BREADEMAX, disk);
		broadcast("DUMP IS AILING!\n");
		msg("This is an unrecoverable error.\n");
		if (!query("Do you want to attempt to continue?")){
			dumpabort(0);
			/*NOTREACHED*/
		} else
			breaderrors = 0;
	}
	/*
	 * Zero buffer, then try to read each sector of buffer separately,
	 * and bypass the cache.
	 */
	memset(buf, 0, size);
	for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) {
		if ((cnt = pread(diskfd, buf, (int)dev_bsize,
		    ((off_t)blkno << dev_bshift))) == dev_bsize)
			continue;
		if (cnt == -1) {
			msg("read error from %s: %s: [sector %d]: count=%ld\n",
				disk, strerror(errno), blkno, dev_bsize);
			continue;
		}
		msg("short read error from %s: [sector %d]: count=%ld, got=%d\n",
			disk, blkno, dev_bsize, cnt);
	}
}
예제 #2
0
partial_check()
#endif
{
	struct mntent *mnt;
	struct stat64 st;

	if (stat64(disk, &st) < 0 ||
	    (st.st_mode & S_IFMT) == S_IFCHR ||
	    (st.st_mode & S_IFMT) == S_IFBLK)
		return;

	partial_dev = st.st_dev;

	setmnttab();
	while (mnt = getmnttab()) {
		st.st_dev = devfromopts(mnt);
		if (st.st_dev == NODEV &&
		    stat64(mnt->mnt_dir, &st) < 0)
			continue;
		if (partial_dev == st.st_dev) {
			if (disk_dynamic) {
				/* LINTED: disk is not NULL */
				free(disk);
			}
			disk = rawname(mnt->mnt_fsname);
			disk_dynamic = (disk != mnt->mnt_fsname);

			partial = 1;
			incno = '0';
			uflag = 0;
			return;
		}
	}
	msg(gettext("`%s' is not on a locally mounted filesystem\n"), disk);
	dumpabort();
	/*NOTREACHED*/
}
예제 #3
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);
}
예제 #4
0
void
bread(ufs2_daddr_t blkno, char *buf, int size)
{
	int secsize, bytes, resid, xfer, base, cnt, i;
	static char *tmpbuf;
	off_t offset;

loop:
	offset = blkno << dev_bshift;
	secsize = sblock->fs_fsize;
	base = offset % secsize;
	resid = size % secsize;
	/*
	 * If the transfer request starts or ends on a non-sector
	 * boundary, we must read the entire sector and copy out
	 * just the part that we need.
	 */
	if (base == 0 && resid == 0) {
		cnt = cread(diskfd, buf, size, offset);
		if (cnt == size)
			return;
	} else {
		if (tmpbuf == NULL && (tmpbuf = malloc(secsize)) == 0)
			quit("buffer malloc failed\n");
		xfer = 0;
		bytes = size;
		if (base != 0) {
			cnt = cread(diskfd, tmpbuf, secsize, offset - base);
			if (cnt != secsize)
				goto bad;
			xfer = MIN(secsize - base, size);
			offset += xfer;
			bytes -= xfer;
			resid = bytes % secsize;
			memcpy(buf, &tmpbuf[base], xfer);
		}
		if (bytes >= secsize) {
			cnt = cread(diskfd, &buf[xfer], bytes - resid, offset);
			if (cnt != bytes - resid)
				goto bad;
			xfer += cnt;
			offset += cnt;
		}
		if (resid == 0)
			return;
		cnt = cread(diskfd, tmpbuf, secsize, offset);
		if (cnt == secsize) {
			memcpy(&buf[xfer], tmpbuf, resid);
			return;
		}
	}
bad:
	if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {
		/*
		 * Trying to read the final fragment.
		 *
		 * NB - dump only works in TP_BSIZE blocks, hence
		 * rounds `dev_bsize' fragments up to TP_BSIZE pieces.
		 * It should be smarter about not actually trying to
		 * read more than it can get, but for the time being
		 * we punt and scale back the read only when it gets
		 * us into trouble. (mkm 9/25/83)
		 */
		size -= dev_bsize;
		goto loop;
	}
	if (cnt == -1)
		msg("read error from %s: %s: [block %jd]: count=%d\n",
			disk, strerror(errno), (intmax_t)blkno, size);
	else
		msg("short read error from %s: [block %jd]: count=%d, got=%d\n",
			disk, (intmax_t)blkno, size, cnt);
	if (++breaderrors > BREADEMAX) {
		msg("More than %d block read errors from %s\n",
			BREADEMAX, disk);
		broadcast("DUMP IS AILING!\n");
		msg("This is an unrecoverable error.\n");
		if (!query("Do you want to attempt to continue?")){
			dumpabort(0);
			/*NOTREACHED*/
		} else
			breaderrors = 0;
	}
	/*
	 * Zero buffer, then try to read each sector of buffer separately,
	 * and bypass the cache.
	 */
	memset(buf, 0, size);
	for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) {
		if ((cnt = pread(diskfd, buf, (int)dev_bsize,
		    ((off_t)blkno << dev_bshift))) == dev_bsize)
			continue;
		if (cnt == -1) {
			msg("read error from %s: %s: [sector %jd]: count=%ld\n",
			    disk, strerror(errno), (intmax_t)blkno, dev_bsize);
			continue;
		}
		msg("short read from %s: [sector %jd]: count=%ld, got=%d\n",
		    disk, (intmax_t)blkno, dev_bsize, cnt);
	}
}