svn commit: r204615 - head/sbin/newfs

Garrett Cooper yanefbsd at gmail.com
Wed Mar 3 08:48:16 UTC 2010


On Tue, Mar 2, 2010 at 8:59 PM, Xin LI <delphij at gmail.com> wrote:
> On Tue, Mar 2, 2010 at 7:19 PM, Maxim Sobolev <sobomax at freebsd.org> wrote:
>> Xin LI wrote:
>>>
>>> On Tue, Mar 2, 2010 at 6:05 PM, Maxim Sobolev <sobomax at freebsd.org> wrote:
>>>>
>>>> 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.
>>>
>>> Bikeshed: why not expand_number()?
>>
>> I did not know that function existed, but even if I did, I am really not
>> sure if adding dependency on external library just to save 200 bytes of code
>> worth it. Considering that newfs(8) is often embedded into various
>> space-tight/custom things, adding dependency could cause more harm than
>> good. In any case, I do not feel strongly about that, so I can change it to
>> use libutil if people feel like it.
>
> [Moved from svn-all@ to -hackers@]
>
> I'd prefer depending on libutil since it's installed as a /lib library
> which is usually available, as libutil is not something easily
> avoidable.
>
> By the way I'm curious why these (humanize and friends) are not
> available as libc function?  Because they are not part of POSIX
> perhaps?

Maxim,

Xin Li has a point. I ran some tests and the ad hoc parsing function
eats up more memory than expand_number(3) [*]:

$ uname -a
FreeBSD garrcoop-fbsd.cisco.com 8.0-STABLE FreeBSD 8.0-STABLE #2: Wed
Feb  3 16:57:07 PST 2010
garrcoop at garrcoop-fbsd.cisco.com:/usr/obj/usr/src/sys/LAPPY_X86  i386

$ gcc -o test_expand_number test_expand_number.c -lutil; strip
test_expand_number; stat -f '%z %b' test_expand_number
3240 8

$ gcc -o test_non-expand_number test_non-expand_number.c; strip
test_non-expand_number; stat -f '%z %b' test_non-expand_number
3756 8

This of course is dynamically linked, not statically linked; the
statically linked size is of course ridiculous:

$ gcc -static -o test_expand_number test_expand_number.c -lutil; strip
test_expand_number; stat -f '%z %b' test_expand_number
184744 364

But just to be fair the non-expand number version is bloody near the
same (only 540 bytes smaller on disk)...

$ gcc -static -o test_non-expand_number test_non-expand_number.c;
strip test_non-expand_number; stat -f '%z %b' test_non-expand_number
184204 360

Given that expand_number(3) is more established and tested, and
supports more prefixes / 64-bit numbers, doesn't it make more sense to
use expand_number(3) given the above evidence?

Thanks,
-Garrett

[*] Notes:
1. All of these numbers were obtained with non-optimized CFLAGS (-O0,
no -march values, etc).
2. All of these numbers were obtained after stripping the binaries as
shown above.

/* Using expand_number(3) */

#include <sys/types.h>
#include <inttypes.h>
#include <libutil.h>
#include <stdint.h>

int
main(void) {

	int64_t anum;

	/*
	 * SYNOPSIS
	     #include <libutil.h>

	     int
	     expand_number(const char *buf, int64_t *num);
	 */
	(void) expand_number("10G", &anum);

	return 0;

}

/* Using parselength. */

#include <sys/types.h>

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

int
main(void) {

	int anum;

	(void) parselength("10G", &anum);

	return 0;

}


More information about the freebsd-hackers mailing list