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); } }
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*/ }
/* * 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); }
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); } }