[PATCH] mkswap: renovation to error printing, usage and option handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



All fprintf(stderr, ...) are converted to use err(), errx(),
warn() or warnx() functions. A bit rough option handling is
converted replaced with getopt_long(), and help output and man
contents are modifed accordingly. Numeric inputs from user are
scrutinize by strtol() instead of letting atoi() do something
silly. New function strtoll_or_err() is added to strutils.h.
Finally few compiler type mismatch warnings where removed by
using correct data types.

Signed-off-by: Sami Kerola <kerolasa@xxxxxx>
---
 disk-utils/Makefile.am |    2 +-
 disk-utils/mkswap.8    |   40 +++----
 disk-utils/mkswap.c    |  301 +++++++++++++++++++++---------------------------
 include/strutils.h     |    1 +
 lib/strutils.c         |   24 ++++
 5 files changed, 178 insertions(+), 190 deletions(-)

diff --git a/disk-utils/Makefile.am b/disk-utils/Makefile.am
index 664c998..c950ff6 100644
--- a/disk-utils/Makefile.am
+++ b/disk-utils/Makefile.am
@@ -28,7 +28,7 @@ swaplabel_SOURCES = swaplabel.c $(utils_common)
 swaplabel_LDADD = $(uuid_ldadd)
 swaplabel_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
 
-mkswap_SOURCES = mkswap.c $(utils_common) $(top_srcdir)/lib/wholedisk.c
+mkswap_SOURCES = mkswap.c $(utils_common) $(top_srcdir)/lib/wholedisk.c $(top_srcdir)/lib/strutils.c
 mkswap_LDADD = $(uuid_ldadd)
 mkswap_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
 
diff --git a/disk-utils/mkswap.8 b/disk-utils/mkswap.8
index 00c089d..e9b65ff 100644
--- a/disk-utils/mkswap.8
+++ b/disk-utils/mkswap.8
@@ -8,16 +8,9 @@
 mkswap \- set up a Linux swap area
 .SH SYNOPSIS
 .B mkswap
-.RB [ \-c ]
-.RB [ \-f ]
-.RB [ \-p
-.IR PSZ ]
-.RB [ \-L
-.IR label ]
-.RB [ \-U
-.IR uuid ]
+.RB [OPTION]
 .I device
-.RI [ size ]
+.RI [size]
 .SH DESCRIPTION
 .B mkswap
 sets up a Linux swap area on a device or in a file.
@@ -75,12 +68,12 @@ label (SUN, BSD, ...) or on a whole disk (e.g. /dev/sda).
 
 .SH OPTIONS
 .TP
-.B \-c
+.BR \-c , " \-\-check"
 Check the device (if it is a block device) for bad blocks
 before creating the swap area.
 If any are found, the count is printed.
 .TP
-.B \-f
+.BR \-f , " \-\-force"
 Force -- go ahead even if the command is stupid.
 This allows the creation of a swap area larger than the file
 or partition it resides on.
@@ -90,41 +83,44 @@ Without this option,
 will refuse to erase the first block on a device with a partition table or on
 a whole disk (e.g. /dev/sda).
 .TP
-.BI \-L \ label
+.BR \-L , " \-\-label" \ device-label
 Specify a label, to allow
 .B swapon
 by label.
 .TP
-.BI \-p \ PSZ
+.BR \-p , " \-\-pagesize" \ PSZ
 Specify the page size (in bytes) to use.  This option is usually unnecessary,
 .B mkswap
 reads the size from the kernel.
 .TP
-.BI \-U \ uuid
+.BR \-U , " \-\-uuid" \ uuid
 Specify the uuid to use.  The default is to generate a UUID.
 .TP
-.BR \-v1
-Specify the swap-space version.  The old \-v0 option has become obsolete
-and now only \-v1 is supported.
+.BR \-v , " \-\-swapversion" \ 1
+Specify the swap-space version.  The old \-v 0 option has become obsolete
+and now only \-v 1 is supported.
 
-The kernel has not supported v0 swap-space format since 2.5.22.
-The new version v1 is supported since 2.1.117.
+The kernel has not supported v0 swap-space format since 2.5.22 (Jun 2002).
+The new version v1 is supported since 2.1.117 (Aug 1998).
+.TP
+.BR \-V , " \-\-version"
+Output version information and exit.
 
 .SH NOTES
 The maximum useful size of a swap area depends on the architecture and
 the kernel version.
 It is roughly 2GiB on i386, PPC, m68k and ARM, 1GiB on sparc, 512MiB on mips,
-128GiB on alpha, and 3TiB on sparc64.  For kernels after 2.3.3 there is no
+128GiB on alpha, and 3TiB on sparc64.  For kernels after 2.3.3 (May 1999) there is no
 such limitation.
 
 Note that before version 2.1.117 the kernel allocated one byte for each page,
 while it now allocates two bytes, so that taking into use a swap area of 2 GiB
 might require 2 MiB of kernel memory.
 
-Presently, Linux allows 32 swap areas (this was 8 before Linux 2.4.10).
+Presently, Linux allows 32 swap areas (this was 8 before Linux 2.4.10 (Sep 2001)).
 The areas in use can be seen in the file
 .I /proc/swaps
-(since 2.1.25).
+(since 2.1.25 (Sep 1997)).
 
 .B mkswap
 refuses areas smaller than 10 pages.
diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c
index 3d14a42..513307b 100644
--- a/disk-utils/mkswap.c
+++ b/disk-utils/mkswap.c
@@ -41,6 +41,8 @@
 #include <sys/utsname.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <err.h>
+#include <getopt.h>
 #ifdef HAVE_LIBSELINUX
 #include <selinux/selinux.h>
 #include <selinux/context.h>
@@ -54,6 +56,7 @@
 #include "pathnames.h"
 #include "wholedisk.h"
 #include "writeall.h"
+#include "xalloc.h"
 
 #ifdef HAVE_LIBUUID
 # ifdef HAVE_UUID_UUID_H
@@ -67,7 +70,6 @@
 # include <blkid.h>
 #endif
 
-static char * program_name = "mkswap";
 static char * device_name = NULL;
 static int DEV = -1;
 static unsigned long long PAGES = 0;
@@ -86,10 +88,13 @@ is_sparc64(void) {
 	struct utsname un;
 	static int sparc64 = -1;
 
-	if (sparc64 != -1) return sparc64;
+	if (sparc64 != -1)
+		return sparc64;
 	sparc64 = 0;
 
-	if (uname(&un) < 0) return 0;
+	if (uname(&un) < 0)
+		return 0;
+
 	if (! strcmp(un.machine, "sparc64")) {
 		sparc64 = 1;
 		return 1;
@@ -142,7 +147,7 @@ is_sparc64(void) {
  * What to do? Let us allow the user to specify the pagesize explicitly.
  *
  */
-static int user_pagesize;
+static long user_pagesize;
 static int pagesize;
 static unsigned long *signature_page = NULL;
 
@@ -153,10 +158,10 @@ init_signature_page(void) {
 
 	if (user_pagesize) {
 		if ((user_pagesize & (user_pagesize-1)) ||
-		    user_pagesize < sizeof(struct swap_header_v1_2) + 10) {
-			fprintf(stderr, _("Bad user-specified page size %d\n"),
+		    (size_t) user_pagesize < sizeof(struct swap_header_v1_2) + 10) {
+			errx(EXIT_FAILURE,
+				_("Bad user-specified page size %lu"),
 				user_pagesize);
-			exit(1);
 		}
 		pagesize = user_pagesize;
 	}
@@ -164,14 +169,9 @@ init_signature_page(void) {
 	if (user_pagesize && user_pagesize != kernel_pagesize)
 		fprintf(stderr, _("Using user-specified page size %d, "
 				  "instead of the system value %d\n"),
-				pagesize, kernel_pagesize);
+			pagesize, kernel_pagesize);
 
-	signature_page = (unsigned long *) calloc(1, pagesize);
-	if (!signature_page) {
-		fprintf(stderr, _("%s: calloc() failed: %s\n"),
-					program_name, strerror(errno));
-		exit(1);
-	}
+	signature_page = (unsigned long *) xcalloc(1, pagesize);
 }
 
 static void
@@ -278,15 +278,18 @@ It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
 static void
 usage(void) {
 	fprintf(stderr,
-		_("Usage: %s [-c] [-pPAGESZ] [-L label] [-U UUID] /dev/name [blocks]\n"),
-		program_name);
-	exit(1);
-}
-
-static void
-die(const char *str) {
-	fprintf(stderr, "%s: %s\n", program_name, str);
-	exit(1);
+		_("Usage: %s [options] device [size]\n\n"),
+		program_invocation_short_name);
+
+	puts(_(	"  -c, --check         check bad blocks before creating the swap area\n"
+		"  -f, --force         force; will allow larger swap than device\n"
+		"  -p, --pagesize      specify page size\n"
+		"  -L, --label         specify label\n"
+		"  -v, --swapversion   specify swap-space version\n"
+		"  -U, --uuid          specify the uuid to use\n"
+		"  -V, --version       print version and exit\n"));
+
+	exit(EXIT_FAILURE);
 }
 
 static void
@@ -294,7 +297,7 @@ page_bad(int page) {
 	struct swap_header_v1_2 *p = (struct swap_header_v1_2 *) signature_page;
 
 	if (badpages == MAX_BADPAGES)
-		die(_("too many bad pages"));
+		errx(EXIT_FAILURE, _("too many bad pages"));
 	p->badpages[badpages] = page;
 	badpages++;
 }
@@ -305,14 +308,12 @@ check_blocks(void) {
 	int do_seek = 1;
 	char *buffer;
 
-	buffer = malloc(pagesize);
-	if (!buffer)
-		die(_("Out of memory"));
+	buffer = xmalloc(pagesize);
 	current_page = 0;
 	while (current_page < PAGES) {
 		if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
 		    current_page*pagesize)
-			die(_("seek failed in check_blocks"));
+			errx(EXIT_FAILURE, _("seek failed in check_blocks"));
 		if ((do_seek = (pagesize != read(DEV, buffer, pagesize))))
 			page_bad(current_page);
 		current_page++;
@@ -342,12 +343,6 @@ get_size(const char  *file) {
 	return size;
 }
 
-static int
-isnzdigit(char c) {
-	return (c >= '1' && c <= '9');
-}
-
-
 /*
  * Check to make certain that our new filesystem won't be created on
  * an already mounted partition.  Code adapted from mke2fs, Copyright
@@ -379,7 +374,8 @@ zap_bootbits(int fd, const char *devname, int force, int is_blkdev)
 
 	if (!force) {
 		if (lseek(fd, 0, SEEK_SET) != 0)
-	                die(_("unable to rewind swap-device"));
+			errx(EXIT_FAILURE,
+				_("unable to rewind swap-device"));
 
 		if (is_blkdev && is_whole_disk_fd(fd, devname)) {
 			/* don't zap bootbits on whole disk -- we know nothing
@@ -390,9 +386,11 @@ zap_bootbits(int fd, const char *devname, int force, int is_blkdev)
 #ifdef HAVE_LIBBLKID_INTERNAL
 			blkid_probe pr = blkid_new_probe();
 			if (!pr)
-				die(_("unable to alloc new libblkid probe"));
+				errx(EXIT_FAILURE,
+					_("unable to alloc new libblkid probe"));
 			if (blkid_probe_set_device(pr, fd, 0, 0))
-				die(_("unable to assign device to libblkid probe"));
+				errx(EXIT_FAILURE,
+					_("unable to assign device to libblkid probe"));
 
 			blkid_probe_enable_partitions(pr, 1);
 			blkid_probe_enable_superblocks(pr, 0);
@@ -401,7 +399,7 @@ zap_bootbits(int fd, const char *devname, int force, int is_blkdev)
 				blkid_probe_lookup_value(pr, "PTTYPE",
 						(const char **) &type, NULL);
 			if (type) {
-				type = strdup(type);
+				type = xstrdup(type);
 				zap = 0;
 			}
 			blkid_free_probe(pr);
@@ -416,23 +414,29 @@ zap_bootbits(int fd, const char *devname, int force, int is_blkdev)
 		char buf[1024];
 
 		if (lseek(fd, 0, SEEK_SET) != 0)
-	                die(_("unable to rewind swap-device"));
+			errx(EXIT_FAILURE,
+				_("unable to rewind swap-device"));
 
 		memset(buf, 0, sizeof(buf));
 		if (write_all(fd, buf, sizeof(buf)))
-			die(_("unable to erase bootbits sectors"));
+			errx(EXIT_FAILURE,
+				_("unable to erase bootbits sectors"));
 		return;
 	}
 
-	fprintf(stderr, _("%s: %s: warning: don't erase bootbits sectors\n"),
-		program_name, devname);
-	if (type)
-		fprintf(stderr, _("        (%s partition table detected). "), type);
-	else if (whole)
-		fprintf(stderr, _("        on whole disk. "));
-	else
-		fprintf(stderr, _("        (compiled without libblkid). "));
-	fprintf(stderr, "Use -f to force.\n");
+	warnx(_("%s: warning: don't erase bootbits sectors"), devname);
+	if (type) {
+		fprintf(stderr,
+			_("        (%s partition table detected). "),
+			type);
+	} else if (whole) {
+		fprintf(stderr,
+			_("        on whole disk. "));
+	} else {
+		fprintf(stderr,
+			_("        (compiled without libblkid). "));
+	}
+	fprintf(stderr, _("Use -f to force.\n"));
 }
 
 int
@@ -440,14 +444,14 @@ main(int argc, char ** argv) {
 	struct stat statbuf;
 	struct swap_header_v1_2 *hdr;
 	int i;
+	int c;
 	unsigned long long maxpages;
 	unsigned long long goodpages;
 	unsigned long long sz;
 	off_t offset;
 	int force = 0;
-	int version = 1;
+	long version = 1;
 	char *block_count = 0;
-	char *pp;
 	char *opt_label = NULL;
 	unsigned char *uuid = NULL;
 #ifdef HAVE_LIBUUID
@@ -455,78 +459,69 @@ main(int argc, char ** argv) {
 	uuid_t uuid_dat;
 #endif
 
-	program_name = (argc && *argv) ? argv[0] : "mkswap";
-	if ((pp = strrchr(program_name, '/')) != NULL)
-		program_name = pp+1;
+	struct option longopts[] = {
+		{ "check",       no_argument,       0, 'c' },
+		{ "force",       no_argument,       0, 'f' },
+		{ "pagesize",    required_argument, 0, 'p' },
+		{ "label",       required_argument, 0, 'L' },
+		{ "swapversion", required_argument, 0, 'v' },
+		{ "uuid",        required_argument, 0, 'U' },
+		{ "version",     no_argument,       0, 'V' },
+		{ NULL,          0, 0, 0 }
+	};
 
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 
-	if (argc == 2 &&
-	    (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
-		printf(_("%s (%s)\n"), program_name, PACKAGE_STRING);
-		exit(0);
-	}
-
-	for (i=1; i<argc; i++) {
-		if (argv[i][0] == '-') {
-			switch (argv[i][1]) {
-				case 'c':
-					check=1;
-					break;
-				case 'f':
-					force=1;
-					break;
-				case 'p':
-					pp = argv[i]+2;
-					if (!*pp && i+1 < argc)
-						pp = argv[++i];
-					if (isnzdigit(*pp))
-						user_pagesize = atoi(pp);
-					else
-						usage();
-					break;
-			        case 'L':
-					pp = argv[i]+2;
-					if (!*pp && i+1 < argc)
-						pp = argv[++i];
-					opt_label = pp;
-				        break;
-				case 'v':
-					version = atoi(argv[i]+2);
-					break;
-				case 'U':
+	while((c = getopt_long(argc, argv, "cfp:L:v:U:V", longopts, NULL)) != -1) {
+		switch (c) {
+		case 'c':
+			check=1;
+			break;
+		case 'f':
+			force=1;
+			break;
+		case 'p':
+			user_pagesize = strtol_or_err(optarg, _("page size error"));
+			break;
+		case 'L':
+			opt_label = optarg;
+			break;
+		case 'v':
+			version = strtol_or_err(optarg, _("version number error"));
+			break;
+		case 'U':
 #ifdef HAVE_LIBUUID
-					opt_uuid = argv[i]+2;
-					if (!*opt_uuid && i+1 < argc)
-						opt_uuid = argv[++i];
+			opt_uuid = optarg;
 #else
-					fprintf(stderr, _("%1$s: warning: ignore -U (UUIDs are unsupported by %1$s)\n"),
-						program_name);
+			errx(_("UUIDs are unsupported"));
 #endif
-					break;
-				default:
-					usage();
-			}
-		} else if (!device_name) {
-			device_name = argv[i];
-		} else if (!block_count) {
-			block_count = argv[i];
-		} else
+			break;
+		case 'V':
+			printf(_("%s (%s)\n"),
+				program_invocation_short_name, PACKAGE_STRING);
+			exit(EXIT_SUCCESS);
+		default:
 			usage();
+		}
 	}
-
-	if (version != 1) {
-		fprintf(stderr, _("%s: does not support swapspace version %d.\n"),
-			program_name, version);
-		exit(EXIT_FAILURE);
+	if (optind < argc) {
+		device_name = argv[optind];
+		optind++;
 	}
+	if (optind < argc)
+		block_count = argv[optind];
+
+	if (version != 1)
+		errx(EXIT_FAILURE,
+			_("does not support swapspace version %lu"),
+			version);
 
 #ifdef HAVE_LIBUUID
 	if(opt_uuid) {
 		if (uuid_parse(opt_uuid, uuid_dat) != 0)
-			die(_("error: UUID parsing failed"));
+			errx(EXIT_FAILURE, _("error: UUID parsing failed"));
 	} else
 		uuid_generate(uuid_dat);
 	uuid = uuid_dat;
@@ -535,42 +530,26 @@ main(int argc, char ** argv) {
 	init_signature_page();	/* get pagesize */
 
 	if (!device_name) {
-		fprintf(stderr,
-			_("%s: error: Nowhere to set up swap on?\n"),
-			program_name);
+		warnx(_("error: Nowhere to set up swap on?"));
 		usage();
 	}
 	if (block_count) {
 		/* this silly user specified the number of blocks explicitly */
-		char *tmp = NULL;
 		long long blks;
-
-		errno = 0;
-		blks = strtoll(block_count, &tmp, 0);
-		if ((tmp == block_count) ||
-		    (tmp && *tmp) ||
-		    (errno != 0 && (blks == LLONG_MAX || blks == LLONG_MIN)) ||
-		    blks < 0)
-			usage();
-
+		blks = strtoll_or_err(block_count, _("problem with size"));
 		PAGES = blks / (pagesize / 1024);
 	}
 	sz = get_size(device_name);
 	if (!PAGES) {
 		PAGES = sz;
-	} else if (PAGES > sz && !force) {
-		fprintf(stderr,
-			_("%s: error: "
-			  "size %llu KiB is larger than device size %llu KiB\n"),
-			program_name,
+	} else if (PAGES > sz && !force)
+		errx(EXIT_FAILURE,
+			_("error: size %llu KiB is larger than device size %llu KiB"),
 			PAGES*(pagesize/1024), sz*(pagesize/1024));
-		exit(1);
-	}
 
 	if (PAGES < MIN_GOODPAGES) {
-		fprintf(stderr,
-			_("%s: error: swap area needs to be at least %ld KiB\n"),
-			program_name, (long)(MIN_GOODPAGES * pagesize/1024));
+		warnx(_("error: swap area needs to be at least %ld KiB"),
+			(long)(MIN_GOODPAGES * pagesize/1024));
 		usage();
 	}
 
@@ -585,9 +564,8 @@ main(int argc, char ** argv) {
 
 	if (PAGES > maxpages) {
 		PAGES = maxpages;
-		fprintf(stderr,
-			_("%s: warning: truncating swap area to %llu KiB\n"),
-			program_name, PAGES * pagesize / 1024);
+		warnx(_("warning: truncating swap area to %llu KiB"),
+			PAGES * pagesize / 1024);
 	}
 
 	if (stat(device_name, &statbuf) < 0) {
@@ -608,17 +586,12 @@ main(int argc, char ** argv) {
 	if (!S_ISBLK(statbuf.st_mode))
 		check=0;
 	else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
-		fprintf(stderr,
-			_("%s: error: "
-			  "will not try to make swapdevice on '%s'\n"),
-			program_name, device_name);
-		exit(1);
+		errx(EXIT_FAILURE, "error: will not try to make swapdevice on '%s'",
+			device_name);
 	} else if (check_mount()) {
-		fprintf(stderr,
-			_("%s: error: "
-			  "%s is mounted; will not make swapspace.\n"),
-			program_name, device_name);
-		exit(1);
+		errx(EXIT_FAILURE,
+			_("error: %s is mounted; will not make swapspace"),
+			device_name);
 	}
 
 	if (check)
@@ -632,7 +605,7 @@ main(int argc, char ** argv) {
 	hdr->nr_badpages = badpages;
 
 	if (badpages > PAGES - MIN_GOODPAGES)
-		die(_("Unable to set up swap-space: unreadable"));
+		errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable"));
 
 	goodpages = PAGES - badpages - 1;
 	printf(_("Setting up swapspace version 1, size = %llu KiB\n"),
@@ -643,12 +616,11 @@ main(int argc, char ** argv) {
 
 	offset = 1024;
 	if (lseek(DEV, offset, SEEK_SET) != offset)
-		die(_("unable to rewind swap-device"));
+		errx(EXIT_FAILURE, _("unable to rewind swap-device"));
 	if (write_all(DEV, (char *) signature_page + offset,
 				    pagesize - offset) == -1) {
-		fprintf(stderr, _("%s: %s: unable to write signature page: %s"),
-			program_name, device_name, strerror(errno));
-		exit(1);
+		err(EXIT_FAILURE, _("%s: unable to write signature page"),
+			device_name);
 	}
 
 	/*
@@ -657,7 +629,7 @@ main(int argc, char ** argv) {
 	 */
 #ifdef HAVE_FSYNC
 	if (fsync(DEV))
-		 die(_("fsync failed"));
+		errx(EXIT_FAILURE, _("fsync failed"));
 #endif
 
 #ifdef HAVE_LIBSELINUX
@@ -667,34 +639,29 @@ main(int argc, char ** argv) {
 		context_t newcontext;
 
 		if (fgetfilecon(DEV, &oldcontext) < 0) {
-			if (errno != ENODATA) {
-				fprintf(stderr, _("%s: %s: unable to obtain selinux file label: %s\n"),
-						program_name, device_name,
-						strerror(errno));
-				exit(1);
-			}
+			if (errno != ENODATA)
+				err(EXIT_FAILURE,
+					_("%s: unable to obtain selinux file label"),
+					device_name);
 			if (matchpathcon(device_name, statbuf.st_mode, &oldcontext))
-				die(_("unable to matchpathcon()"));
+				errx(EXIT_FAILURE,
+					_("unable to matchpathcon()"));
 		}
 		if (!(newcontext = context_new(oldcontext)))
-			die(_("unable to create new selinux context"));
+			errx(EXIT_FAILURE, _("unable to create new selinux context"));
 		if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE))
-			die(_("couldn't compute selinux context"));
+			errx(EXIT_FAILURE, _("couldn't compute selinux context"));
 
 		context_string = context_str(newcontext);
 
 		if (strcmp(context_string, oldcontext)!=0) {
-			if (fsetfilecon(DEV, context_string)) {
-				fprintf(stderr, _("%s: unable to relabel %s to %s: %s\n"),
-						program_name, device_name,
-						context_string,
-						strerror(errno));
-				exit(1);
-			}
+			if (fsetfilecon(DEV, context_string))
+				err(EXIT_FAILURE, _("unable to relabel %s to %s"),
+					device_name, context_string);
 		}
 		context_free(newcontext);
 		freecon(oldcontext);
 	}
 #endif
-	return 0;
+	return EXIT_SUCCESS;
 }
diff --git a/include/strutils.h b/include/strutils.h
index 462332d..99d8acd 100644
--- a/include/strutils.h
+++ b/include/strutils.h
@@ -7,6 +7,7 @@
 
 extern int strtosize(const char *str, uintmax_t *res);
 extern long strtol_or_err(const char *str, const char *errmesg);
+extern long long strtoll_or_err(const char *str, const char *errmesg);
 
 #ifndef HAVE_STRNLEN
 extern size_t strnlen(const char *s, size_t maxlen);
diff --git a/lib/strutils.c b/lib/strutils.c
index 94635b1..6c60ac1 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -188,6 +188,30 @@ err:
                errx(EXIT_FAILURE, "%s: '%s'", errmesg, str);
        return 0;
 }
+/*
+ * same as strtoll(3) but exit on failure instead of returning crap
+ */
+long long strtoll_or_err(const char *str, const char *errmesg)
+{
+	long long int num;
+	char *end = NULL;
+
+	if (str == NULL || *str == '\0')
+		goto err;
+	errno = 0;
+	num = strtoll(str, &end, 10);
+
+	if (errno || (end && *end))
+		goto err;
+
+	return num;
+err:
+	if (errno)
+		err(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+	else
+		errx(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+	return 0;
+}
 
 /*
  * Converts stat->st_mode to ls(1)-like mode string. The size of "str" must
-- 
1.7.3.5

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux