diff options
author | pi <pi@FreeBSD.org> | 2015-03-02 04:08:57 +0800 |
---|---|---|
committer | pi <pi@FreeBSD.org> | 2015-03-02 04:08:57 +0800 |
commit | a0be67aab85ec8f8413a8f7b08b955381f0bf3db (patch) | |
tree | 01a8f68c87e3b5a22bfc7e0aaa013782c5632ed4 /sysutils | |
parent | 3fdd3e57d6fa2a9ef23c51bc0aca3b38f1da533c (diff) | |
download | freebsd-ports-gnome-a0be67aab85ec8f8413a8f7b08b955381f0bf3db.tar.gz freebsd-ports-gnome-a0be67aab85ec8f8413a8f7b08b955381f0bf3db.tar.zst freebsd-ports-gnome-a0be67aab85ec8f8413a8f7b08b955381f0bf3db.zip |
sysutils/diskcheckd: 20110729 -> 20150220
adapt to missing DIOCGDINFO on 11-current and fix some printf warnings
PR: 197841
Submitted by: Perry Hutchison <perryh_bsd_bugs@pluto.rain.com> (maintainer)
Diffstat (limited to 'sysutils')
-rw-r--r-- | sysutils/diskcheckd/Makefile | 2 | ||||
-rw-r--r-- | sysutils/diskcheckd/files/diskcheckd.8 | 15 | ||||
-rw-r--r-- | sysutils/diskcheckd/files/diskcheckd.c | 158 |
3 files changed, 154 insertions, 21 deletions
diff --git a/sysutils/diskcheckd/Makefile b/sysutils/diskcheckd/Makefile index bcc23379bfb3..1519d2a25d4d 100644 --- a/sysutils/diskcheckd/Makefile +++ b/sysutils/diskcheckd/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PORTNAME= diskcheckd -PORTVERSION= 20110729 +PORTVERSION= 20150220 CATEGORIES= sysutils MASTER_SITES= # part of port DISTFILES= # part of port diff --git a/sysutils/diskcheckd/files/diskcheckd.8 b/sysutils/diskcheckd/files/diskcheckd.8 index 2fb72e7b994c..bcf4156ce246 100644 --- a/sysutils/diskcheckd/files/diskcheckd.8 +++ b/sysutils/diskcheckd/files/diskcheckd.8 @@ -199,9 +199,18 @@ and this manual page were written by .An Ben Smithurst Aq ben@FreeBSD.org , with input from .An Poul-Henning Kamp Aq phk@FreeBSD.org . +The geom-aware version of the sector->partition translation code was added by +.An Perry Hutchison Aq perryh@pluto.rain.com , +based on a mechanism suggested by +.An Warner Losh Aq imp@bsdimp.com . .Sh BUGS .Nm -assumes all disks have 512 byte sectors. +Too much of the code assumes all disks have 512 byte sectors. .Pp -The code that attempts to identify and report which slice and partition -contain a detected error does not understand GPT partitions. +There are two versions of the code that attempts to identify +and report which slice and/or partition contain a detected error. +The older version, used when the DIOCGDINFO ioctl is available +(i.e. prior to +.Fx 11.0 ), +does not understand either GPT partitions or dedicated BSD disks +(having the BSD disklabel in place of an MBR). diff --git a/sysutils/diskcheckd/files/diskcheckd.c b/sysutils/diskcheckd/files/diskcheckd.c index 6177eb38bdf7..f3ec420139d3 100644 --- a/sysutils/diskcheckd/files/diskcheckd.c +++ b/sysutils/diskcheckd/files/diskcheckd.c @@ -22,6 +22,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * geom-aware portions of logreaderror() Copyright (c) 2015 Perry Hutchison + * <perryh@pluto.rain.com>, licensed on the same terms as above. */ static const char rcsid[] = @@ -58,6 +61,19 @@ static const char rcsid[] = #define READ_SIZE (64 << 10) +/* + * Customize format strings according to what printf et al. want for a quad_t. + * + * This should not be necessary -- the whole point of %qd is to match a quad_t + * -- but in LP64 a quad_t is the same size as a long and yet %qd is treated as + * equivalent to %lld (which is correct only if a long is 32 bits, as in ILP32). + */ +#ifdef LP64 +#define QD "%ld" +#else +#define QD "%qd" +#endif + struct disk { int fd; char *device; @@ -125,10 +141,11 @@ main(int argc, char *argv[]) { initial_debug = debug; - openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0), LOG_DAEMON); + openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0), + LOG_DAEMON); if (!debug && daemon(0, 0) < 0) { - syslog(LOG_NOTICE, "daemon failure: %m"); + syslog(LOG_NOTICE, "daemon() failure: %m"); exit(EXIT_FAILURE); } @@ -309,26 +326,40 @@ void logreaderror(struct disk *dp, int nbytes) { quad_t secno; off_t saved_offset; + char newdev[512]; + +#ifdef DIOCGDINFO int fd, slice, part; struct dos_partition *dos; struct disklabel label; char buf[512]; - char newdev[512]; +#else /* DIOCGDINFO */ + static size_t geomSize = 0; + static char * geomConf = NULL; + char * cp; + static size_t partLen = 31; + static char *part = NULL; + quad_t relsec = -1; + char *typefld = NULL; +#endif /* DIOCGDINFO */ saved_offset = dseek(dp, 0, SEEK_CUR); secno = (quad_t)saved_offset / dp->secsize; dp->errors++; - syslog(LOG_NOTICE, "error reading %d bytes from sector %qd on %s", + syslog(LOG_NOTICE, "error reading %d bytes from sector " QD " on %s", nbytes, secno, dp->device); +#ifdef DIOCGDINFO /* * First, find out which slice it's in. To do this, we seek to the * start of the disk, read the first sector, and go through the DOS * slice table. */ - if (dseek(dp, 0, SEEK_SET) == -1) + if (dseek(dp, 0, SEEK_SET) == -1) { + syslog(LOG_NOTICE, "could not seek to start of disk: %m"); exit(EXIT_FAILURE); + } if (read(dp->fd, buf, sizeof buf) != sizeof buf) { dseek(dp, saved_offset, SEEK_SET); @@ -336,9 +367,14 @@ logreaderror(struct disk *dp, int nbytes) { } /* seek back to where we were */ - if (dseek(dp, saved_offset, SEEK_SET) == -1) + if (dseek(dp, saved_offset, SEEK_SET) == -1) { + syslog(LOG_NOTICE, + "could not seek to previous position" + "after reading first sector: %m"); exit(EXIT_FAILURE); + } + // TODO: should validate DOS partition table (vs GPT or dedicated) dos = (struct dos_partition *)&buf[DOSPARTOFF]; for (slice = 0; slice < NDOSPART; slice++) if (dos[slice].dp_start <= secno && @@ -347,7 +383,7 @@ logreaderror(struct disk *dp, int nbytes) { if (slice == NDOSPART) { syslog(LOG_NOTICE, - "sector %qd on %s doesn't appear " + "sector " QD " on %s doesn't appear " "to be within any DOS slice", secno, dp->device); return; } @@ -361,8 +397,8 @@ logreaderror(struct disk *dp, int nbytes) { /* Check the type of that partition. */ if (dos[slice].dp_typ != DOSPTYP_386BSD) { /* If not a BSD slice, we can't do much more. */ - syslog(LOG_NOTICE, "last bad sector is sector %qd " - "on device %s, type %02x", secno, newdev, + syslog(LOG_NOTICE, "last bad sector is sector " QD + " on device %s, type %02x", secno, newdev, dos[slice].dp_typ); return; } @@ -389,7 +425,7 @@ logreaderror(struct disk *dp, int nbytes) { if (part == MAXPARTITIONS) { syslog(LOG_NOTICE, - "sector %qd on %s doesn't appear " + "sector " QD " on %s doesn't appear " "to be within any BSD partition", secno, newdev); return; } @@ -400,14 +436,100 @@ logreaderror(struct disk *dp, int nbytes) { syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev); if (label.d_partitions[part].p_fstype != FS_BSDFFS) { /* Again, if not a BSD partition, can't do much. */ - syslog(LOG_NOTICE, "last bad sector is sector %qd " - "on device %s, type %s", secno, newdev, + syslog(LOG_NOTICE, "last bad sector is sector " QD + " on device %s, type %s", secno, newdev, fstypename(label.d_partitions[part].p_fstype)); return; } +#else /* DIOCGDINFO */ + if (geomSize == 0) { + sysctlbyname("kern.geom.conftxt", NULL, &geomSize, NULL, 0); + if (geomSize <= 0) { + printf("sysctlbyname() returned size = %d\n", geomSize); + geomSize = 0; + exit(EXIT_FAILURE); + } + geomConf = malloc(geomSize); + if (geomConf == NULL) { + printf("malloc(%d) returned NULL\n", geomSize); + geomSize = 0; + exit(EXIT_FAILURE); + } + if (sysctlbyname("kern.geom.conftxt", geomConf, &geomSize, + NULL, 0) != 0) { + perror("sysctlbyname()"); + geomSize = 0; + free(geomConf); + geomConf = NULL; + exit(EXIT_FAILURE); + } + } + if (part == NULL) + part = malloc(partLen + 1); + + for ( cp = geomConf ; *cp ; ++cp ) { + // find line "0 DISK " matching current disk, using + // strncmp because where cp points is not null-terminated + // (All DISK lines, and only DISK lines, are at level 0.) + // Magic numbers: 7 == strlen("0 DISK "); 5 == strlen("/dev/") + if (strncmp(cp, "0 DISK ", 7) == 0 + && strncmp(&cp[7], &dp->device[5], strlen(dp->device) - 5) == 0 + && cp[7 + strlen(dp->device) - 5] == ' ') { + for (;;) { + // scan to end of line + while (cp[1] && *cp != '\n') + ++cp; + ++cp; // start of next line + // Find PART line containing the failed sector; + // must be on same disk => stop upon finding + // another DISK line. If more than one matching + // PART -- due to nested geoms -- use the last + // (innermost). + if (*cp == '\0' || *cp == '0') + break; // end of current DISK's entries + // scan to end of level number + while (cp[1] && *cp != ' ') + ++cp; + if (strncmp(cp, " PART ", 6) == 0) { + char *pp = &cp[6]; + int pl = strchr(pp, ' ') - pp; + quad_t mediasize, offset; + long secsize; + + cp = pp + pl; // cp -> mediasize + mediasize = strtoq(cp, &cp, 10); + secsize = strtol(cp, &cp, 10); + mediasize /= secsize; + cp = strchr(cp, 'o') + 1; + offset = strtoq(cp, &cp, 10) / secsize; + if (secno >= offset + && (secno - offset) < mediasize) { + if (pl > partLen) { + part = realloc(part, + pl+1); + partLen = pl; + } + strncpy(part, pp, pl); + part[pl] = '\0'; + relsec = secno - offset; + typefld = cp + 1; + } + } + } + } + // scan to end of line + while (cp[1] && *cp != '\n') + ++cp; + } +//// printf("part %s, relsec %qd, typefld %p: %.27s\n", +//// part, relsec, typefld, typefld); + secno = relsec; + strncpy(newdev, part, sizeof(newdev) - 1); + newdev[sizeof(newdev) - 1] = '\0'; // paranoia +#endif /* DIOCGDINFO */ - syslog(LOG_NOTICE, "last bad sector is sector %qd " - "on 4.2BSD filesystem %s", secno, newdev); + syslog(LOG_NOTICE, "last bad sector is sector " QD + " on 4.2BSD filesystem %s", secno, newdev); /* * XXX: todo: find out which file on the BSD filesystem uses this @@ -472,12 +594,14 @@ writeoffsets(struct disk *disks, const char *save_file) { "#\tposition/size\tdays\trate\terrors\tintvl\tnext\n"); for (dp = disks; dp->device != NULL; dp++) if (strcmp(dp->device, "*") != 0) { - fprintf(fp, "%s %qd\n", dp->device, + fprintf(fp, "%s " QD "\n", dp->device, (quad_t)dseek(dp, 0, SEEK_CUR)); if (debug) { - fprintf(stderr, "%s %qd\n", dp->device, + fprintf(stderr, "%s " QD "\n", dp->device, (quad_t)dseek(dp, 0, SEEK_CUR)); - fprintf(stderr, "#\t%qd\t%d\t%d\t%d\t%qd\t%qd\n", + fprintf(stderr, + "#\t" QD "\t%d\t%d\t%d\t" QD "\t" QD + "\n", (quad_t)dp->size, dp->days, dp->rate, dp->errors, dp->interval, dp->next); } |