From owner-svn-src-all@FreeBSD.ORG Wed Mar 3 02:05:10 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 461CA106566C; Wed, 3 Mar 2010 02:05:10 +0000 (UTC) (envelope-from sobomax@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 349F98FC08; Wed, 3 Mar 2010 02:05:10 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o2325AxQ010091; Wed, 3 Mar 2010 02:05:10 GMT (envelope-from sobomax@svn.freebsd.org) Received: (from sobomax@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o2325AMY010089; Wed, 3 Mar 2010 02:05:10 GMT (envelope-from sobomax@svn.freebsd.org) Message-Id: <201003030205.o2325AMY010089@svn.freebsd.org> From: Maxim Sobolev Date: Wed, 3 Mar 2010 02:05:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r204615 - head/sbin/newfs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Mar 2010 02:05:10 -0000 Author: sobomax Date: Wed Mar 3 02:05:09 2010 New Revision: 204615 URL: http://svn.freebsd.org/changeset/base/204615 Log: Teach newfs(8) to understand size modifiers for all options taking size or size-like argument. I.e. "-s 32k" instead of "-s 32768". Size parsing function has been shamelessly stolen from the truncate(1). I'm sure many sysadmins out there will appreciate this small improvement. MFC after: 1 week Modified: head/sbin/newfs/newfs.c Modified: head/sbin/newfs/newfs.c ============================================================================== --- head/sbin/newfs/newfs.c Wed Mar 3 01:12:16 2010 (r204614) +++ head/sbin/newfs/newfs.c Wed Mar 3 02:05:09 2010 (r204615) @@ -117,6 +117,7 @@ static void getfssize(intmax_t *, const static struct disklabel *getdisklabel(char *s); static void rewritelabel(char *s, struct disklabel *lp); static void usage(void); +static int parselength(const char *ls, int *sz); ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */ @@ -129,7 +130,7 @@ main(int argc, char *argv[]) struct stat st; char *cp, *special; intmax_t reserved; - int ch, i; + int ch, i, rval; off_t mediasize; char part_name; /* partition name, default to full disk */ @@ -169,7 +170,8 @@ main(int argc, char *argv[]) Rflag = 1; break; case 'S': - if ((sectorsize = atoi(optarg)) <= 0) + rval = parselength(optarg, §orsize); + if (rval < 0 || sectorsize <= 0) errx(1, "%s: bad sector size", optarg); break; case 'T': @@ -182,12 +184,17 @@ main(int argc, char *argv[]) Xflag++; break; case 'a': - if ((maxcontig = atoi(optarg)) <= 0) + rval = parselength(optarg, &maxcontig); + if (rval < 0 || maxcontig <= 0) errx(1, "%s: bad maximum contiguous blocks", optarg); break; case 'b': - if ((bsize = atoi(optarg)) < MINBSIZE) + rval = parselength(optarg, &bsize); + if (rval < 0) + errx(1, "%s: bad block size", + optarg); + if (bsize < MINBSIZE) errx(1, "%s: block size too small, min is %d", optarg, MINBSIZE); if (bsize > MAXBSIZE) @@ -195,33 +202,40 @@ main(int argc, char *argv[]) optarg, MAXBSIZE); break; case 'c': - if ((maxblkspercg = atoi(optarg)) <= 0) + rval = parselength(optarg, &maxblkspercg); + if (rval < 0 || maxblkspercg <= 0) errx(1, "%s: bad blocks per cylinder group", optarg); break; case 'd': - if ((maxbsize = atoi(optarg)) < MINBSIZE) + rval = parselength(optarg, &maxbsize); + if (rval < 0 || maxbsize < MINBSIZE) errx(1, "%s: bad extent block size", optarg); break; case 'e': - if ((maxbpg = atoi(optarg)) <= 0) + rval = parselength(optarg, &maxbpg); + if (rval < 0 || maxbpg <= 0) errx(1, "%s: bad blocks per file in a cylinder group", optarg); break; case 'f': - if ((fsize = atoi(optarg)) <= 0) + rval = parselength(optarg, &fsize); + if (rval < 0 || fsize <= 0) errx(1, "%s: bad fragment size", optarg); break; case 'g': - if ((avgfilesize = atoi(optarg)) <= 0) + rval = parselength(optarg, &avgfilesize); + if (rval < 0 || avgfilesize <= 0) errx(1, "%s: bad average file size", optarg); break; case 'h': - if ((avgfilesperdir = atoi(optarg)) <= 0) + rval = parselength(optarg, &avgfilesperdir); + if (rval < 0 || avgfilesperdir <= 0) errx(1, "%s: bad average files per dir", optarg); break; case 'i': - if ((density = atoi(optarg)) <= 0) + rval = parselength(optarg, &density); + if (rval < 0 || density <= 0) errx(1, "%s: bad bytes per inode", optarg); break; case 'l': @@ -481,3 +495,62 @@ usage() fprintf(stderr, "\t-s file system size (sectors)\n"); exit(1); } + +/* + * Return the numeric value of a string given in the form [+-][0-9]+[GMKT] + * or -1 on format error or overflow. + */ +static int +parselength(const char *ls, int *sz) +{ + off_t length, oflow; + int lsign; + + length = 0; + lsign = 1; + + switch (*ls) { + case '-': + lsign = -1; + case '+': + ls++; + } + +#define ASSIGN_CHK_OFLOW(x, y) if (x < y) return -1; y = x + /* + * Calculate the value of the decimal digit string, failing + * on overflow. + */ + while (isdigit(*ls)) { + oflow = length * 10 + *ls++ - '0'; + ASSIGN_CHK_OFLOW(oflow, length); + } + + switch (*ls) { + case 'T': + case 't': + oflow = length * 1024; + ASSIGN_CHK_OFLOW(oflow, length); + case 'G': + case 'g': + oflow = length * 1024; + ASSIGN_CHK_OFLOW(oflow, length); + case 'M': + case 'm': + oflow = length * 1024; + ASSIGN_CHK_OFLOW(oflow, length); + case 'K': + case 'k': + if (ls[1] != '\0') + return -1; + oflow = length * 1024; + ASSIGN_CHK_OFLOW(oflow, length); + case '\0': + break; + default: + return -1; + } + + *sz = length * lsign; + return 0; +}