aboutsummaryrefslogtreecommitdiffstats
path: root/sysutils
diff options
context:
space:
mode:
authorpi <pi@FreeBSD.org>2015-03-02 04:08:57 +0800
committerpi <pi@FreeBSD.org>2015-03-02 04:08:57 +0800
commita0be67aab85ec8f8413a8f7b08b955381f0bf3db (patch)
tree01a8f68c87e3b5a22bfc7e0aaa013782c5632ed4 /sysutils
parent3fdd3e57d6fa2a9ef23c51bc0aca3b38f1da533c (diff)
downloadfreebsd-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/Makefile2
-rw-r--r--sysutils/diskcheckd/files/diskcheckd.815
-rw-r--r--sysutils/diskcheckd/files/diskcheckd.c158
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);
}