Subject: Re: disklabeling a 1.7 TB disk
To: David Laight <david@l8s.co.uk>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: current-users
Date: 02/29/2004 06:43:52
>>On Fri, Feb 27, 2004 at 05:51:31PM -0500, Jan Schaumann wrote:
>>> Ok, I'm going completely insane here.  I have a 1.7 TB disk, that I'm
>>> desparately trying to disklabel.  So:
>>
>>> cylinders: -869262
>>> total sectors: -876216576
>>
>>printfs now fixed in current.
>>
>>> Ok, so I think: how about I correct the faulty fields?  I fix 'total
>>
>>> total sectors: 2147483647
>>
>>This patch should fix disklabel so that it will accept up to 2^32-1
>>for important fields.
>>
>>Going beyond 2^32 sectors is hard.....
>
>	btw, NXTNUM/NXTXNUM has problem with _CHECKLINE (_CHECKLINE tries to
>	"break" out of the loop, but NXTNUM/NXTXNUM is wrapped by do-while
>	so _CHECKLINE does not function correctly.

	more error check to strtoul().

itojun


Index: disklabel.c
===================================================================
RCS file: /cvsroot/src/sbin/disklabel/disklabel.c,v
retrieving revision 1.126
diff -u -r1.126 disklabel.c
--- disklabel.c	18 Jan 2004 22:34:22 -0000	1.126
+++ disklabel.c	28 Feb 2004 21:44:12 -0000
@@ -1458,13 +1458,15 @@
 			continue;
 		}
 		if (!strcmp(cp, "total sectors")) {
-			v = atoi(tp);
-			if (v <= 0) {
+			char *ep;
+			errno = 0;
+			lp->d_secperunit = strtoul(tp, &ep, 10);
+			if (*tp == '\0' || !ep || *ep != '\0' ||
+			    errno == ERANGE) {
 				warnx("line %d: bad %s: %s", lineno, cp, tp);
 				errors++;
 			} else
-				lp->d_secperunit = v;
-			continue;
+				continue;
 		}
 		if (!strcmp(cp, "rpm")) {
 			v = atoi(tp);
@@ -1538,19 +1540,22 @@
 		break;						\
 	}
 
-#define NXTNUM(n) do { \
+/* cannot use do-while due to the use of "break" in _CHECKLINE */
+#define NXTNUM(n) { \
 	_CHECKLINE						\
 	cp = tp, tp = word(cp), (n) = (cp != NULL ? atoi(cp) : 0);	\
-} while (/* CONSTCOND */ 0)
+}
 
-#define NXTXNUM(n) do { \
+/* cannot use do-while due to the use of "break" in _CHECKLINE */
+#define NXTXNUM(n) { \
 	char	*ptr;							\
-	int	 m;							\
+	u_int32_t m;							\
 									\
 	_CHECKLINE							\
 	cp = tp, tp = word(cp);						\
-	m = (int)strtol(cp, &ptr, 10);					\
-	if (*ptr == '\0')						\
+	errno = 0;							\
+	m = strtoul(cp, &ptr, 10);					\
+	if (*cp && ptr && *ptr == '\0' && errno == 0)			\
 		(n) = m;						\
 	else {								\
 		if (*ptr++ != '/') {					\
@@ -1559,32 +1564,27 @@
 			break;						\
 		}							\
 		(n) = m * lp->d_secpercyl;				\
-		m = (int)strtol(ptr, &ptr, 10);				\
-		if (*ptr++ != '/') {					\
+		errno = 0;						\
+		m = strtoul(ptr, &ptr, 10);				\
+		if (!ptr || *ptr++ != '/' || errno == ERANGE) {		\
 			warnx("line %d: invalid format", lineno);	\
 			errors++;					\
 			break;						\
 		}							\
 		(n) += m * lp->d_nsectors;				\
-		m = (int)strtol(ptr, &ptr, 10);				\
+		errno = 0;						\
+		m = strtoul(ptr, &ptr, 10);				\
+		if (!ptr || *ptr != '\0' || errno == ERANGE) {		\
+			warnx("line %d: invalid format", lineno);	\
+			errors++;					\
+			break;						\
+		}							\
 		(n) += m;						\
 	}								\
-} while (/* CONSTCOND */ 0)
+}
 
-			NXTXNUM(v);
-			if (v < 0) {
-				warnx("line %d: bad partition size: %s",
-				    lineno, cp);
-				errors++;
-			} else
-				pp->p_size = v;
-			NXTXNUM(v);
-			if (v < 0) {
-				warnx("line %d: bad partition offset: %s",
-				    lineno, cp);
-				errors++;
-			} else
-				pp->p_offset = v;
+			NXTXNUM(pp->p_size);
+			NXTXNUM(pp->p_offset);
 			/* can't use word() here because of blanks
 			   in fstypenames[] */
 			_CHECKLINE