From 0f004afe33d8a836e7b9c97b3a45dae4d763c5b5 Mon Sep 17 00:00:00 2001 From: christos Date: Tue, 1 Dec 2015 23:29:07 +0000 Subject: [PATCH] merge command line parsers and check all memory allocations. --- sbin/gpt/add.c | 20 ++----- sbin/gpt/biosboot.c | 25 +++------ sbin/gpt/gpt.c | 127 +++++++++++++++++++++++++++----------------- sbin/gpt/gpt.h | 3 ++ sbin/gpt/gpt_uuid.c | 36 ++++++++----- sbin/gpt/gpt_uuid.h | 3 +- sbin/gpt/label.c | 45 ++++++++++------ sbin/gpt/show.c | 8 +-- 8 files changed, 148 insertions(+), 119 deletions(-) diff --git a/sbin/gpt/add.c b/sbin/gpt/add.c index fc18f6e08b80..3d424467ad0f 100644 --- a/sbin/gpt/add.c +++ b/sbin/gpt/add.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: add.c,v 1.33 2015/12/01 19:25:24 christos Exp $"); +__RCSID("$NetBSD: add.c,v 1.34 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -152,28 +152,19 @@ static int cmd_add(gpt_t gpt, int argc, char *argv[]) { int ch; - int64_t human_num; while ((ch = getopt(argc, argv, GPT_AIS "bl:t:")) != -1) { switch(ch) { case 'b': - if (block > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - block = human_num; - if (block < 1) + if (gpt_human_get(&block) == -1) return usage(); break; case 'l': - if (name != NULL) + if (gpt_name_get(gpt, &name) == -1) return usage(); - name = (uint8_t *)strdup(optarg); break; case 't': - if (!gpt_uuid_is_nil(type)) - return usage(); - if (gpt_uuid_parse(optarg, type) != 0) + if (gpt_uuid_get(gpt, &type) == -1) return usage(); break; default: @@ -188,9 +179,8 @@ cmd_add(gpt_t gpt, int argc, char *argv[]) return usage(); /* Create NetBSD FFS partitions by default. */ - if (gpt_uuid_is_nil(type)) { + if (gpt_uuid_is_nil(type)) gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0); - } if (optind != argc) return usage(); diff --git a/sbin/gpt/biosboot.c b/sbin/gpt/biosboot.c index 0ded07d98bc4..0d3501461c33 100644 --- a/sbin/gpt/biosboot.c +++ b/sbin/gpt/biosboot.c @@ -1,4 +1,4 @@ -/* $NetBSD: biosboot.c,v 1.17 2015/12/01 16:32:19 christos Exp $ */ +/* $NetBSD: biosboot.c,v 1.18 2015/12/01 23:29:07 christos Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ #include #ifdef __RCSID -__RCSID("$NetBSD: biosboot.c,v 1.17 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: biosboot.c,v 1.18 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -252,34 +252,23 @@ cmd_biosboot(gpt_t gpt, int argc, char *argv[]) #ifdef DIOCGWEDGEINFO struct dkwedge_info dkw; #endif - char *dev, *p; + char *dev; int ch; gpt_t ngpt = gpt; while ((ch = getopt(argc, argv, "c:i:L:")) != -1) { switch(ch) { case 'c': - if (bootpath != NULL) - usage(); - if ((bootpath = strdup(optarg)) == NULL) { - gpt_warn(gpt, "strdup failed"); - return -1; - } + if (gpt_name_get(gpt, &bootpath) == -1) + return usage(); break; case 'i': - if (entry > 0) - usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) + if (gpt_entry_get(&entry) == -1) return usage(); break; case 'L': - if (label != NULL) + if (gpt_name_get(gpt, &label) == -1) return usage(); - if ((label = (uint8_t *)strdup(optarg)) == NULL) { - gpt_warn(gpt, "strdup failed"); - return -1; - } break; default: return usage(); diff --git a/sbin/gpt/gpt.c b/sbin/gpt/gpt.c index 297ee9cd6765..d0dc31a96ca5 100644 --- a/sbin/gpt/gpt.c +++ b/sbin/gpt/gpt.c @@ -35,7 +35,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: gpt.c,v 1.51 2015/12/01 19:25:24 christos Exp $"); +__RCSID("$NetBSD: gpt.c,v 1.52 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -850,7 +850,8 @@ gpt_create(gpt_t gpt, off_t last, u_int parts, int primary_only) hdr->hdr_lba_alt = htole64(last); hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks); hdr->hdr_lba_end = htole64(last - blocks - 1LL); - gpt_uuid_generate(hdr->hdr_guid); + if (gpt_uuid_generate(gpt, hdr->hdr_guid) == -1) + return -1; hdr->hdr_lba_table = htole64(gpt->tbl->map_start); hdr->hdr_entries = htole32((blocks * gpt->secsz) / sizeof(struct gpt_ent)); @@ -860,7 +861,8 @@ gpt_create(gpt_t gpt, off_t last, u_int parts, int primary_only) ent = gpt->tbl->map_data; for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - gpt_uuid_generate(ent[i].ent_guid); + if (gpt_uuid_generate(gpt, ent[i].ent_guid) == -1) + return -1; } /* @@ -895,12 +897,50 @@ gpt_create(gpt_t gpt, off_t last, u_int parts, int primary_only) return last; } -int -gpt_add_find(gpt_t gpt, struct gpt_find *find, int ch) +static int +gpt_size_get(gpt_t gpt, off_t *size) { + off_t sectors; int64_t human_num; char *p; + if (*size > 0) + return -1; + sectors = strtoll(optarg, &p, 10); + if (sectors < 1) + return -1; + if (*p == '\0' || ((*p == 's' || *p == 'S') && p[1] == '\0')) { + *size = sectors * gpt->secsz; + return 0; + } + if ((*p == 'b' || *p == 'B') && p[1] == '\0') { + *size = sectors; + return 0; + } + if (dehumanize_number(optarg, &human_num) < 0) + return -1; + *size = human_num; + return 0; +} + +int +gpt_human_get(off_t *human) +{ + int64_t human_num; + + if (*human > 0) + return -1; + if (dehumanize_number(optarg, &human_num) < 0) + return -1; + *human = human_num; + if (*human < 1) + return -1; + return 0; +} + +int +gpt_add_find(gpt_t gpt, struct gpt_find *find, int ch) +{ switch (ch) { case 'a': if (find->all > 0) @@ -908,31 +948,19 @@ gpt_add_find(gpt_t gpt, struct gpt_find *find, int ch) find->all = 1; break; case 'b': - if (find->block > 0) - return -1; - if (dehumanize_number(optarg, &human_num) < 0) - return -1; - find->block = human_num; - if (find->block < 1) + if (gpt_human_get(&find->block) == -1) return -1; break; case 'i': - if (find->entry > 0) - return -1; - find->entry = strtoul(optarg, &p, 10); - if (*p != 0 || find->entry < 1) + if (gpt_entry_get(&find->entry) == -1) return -1; break; case 'L': - if (find->label != NULL) + if (gpt_name_get(gpt, &find->label) == -1) return -1; - find->label = (uint8_t *)strdup(optarg); break; case 's': - if (find->size > 0) - return -1; - find->size = strtoll(optarg, &p, 10); - if (*p != 0 || find->size < 1) + if (gpt_size_get(gpt, &find->size) == -1) return -1; break; case 't': @@ -1008,44 +1036,18 @@ gpt_change_ent(gpt_t gpt, const struct gpt_find *find, int gpt_add_ais(gpt_t gpt, off_t *alignment, u_int *entry, off_t *size, int ch) { - int64_t human_num; - off_t sectors; - char *p; - switch (ch) { case 'a': - if (*alignment > 0) - return -1; - if (dehumanize_number(optarg, &human_num) < 0) - return -1; - *alignment = human_num; - if (*alignment < 1) + if (gpt_human_get(alignment) == -1) return -1; return 0; case 'i': - if (*entry > 0) - return -1; - *entry = strtoul(optarg, &p, 10); - if (*p != 0 || *entry < 1) + if (gpt_entry_get(entry) == -1) return -1; return 0; case 's': - if (*size > 0) + if (gpt_size_get(gpt, size) == -1) return -1; - sectors = strtoll(optarg, &p, 10); - if (sectors < 1) - return -1; - if (*p == '\0' || ((*p == 's' || *p == 'S') && p[1] == '\0')) { - *size = sectors * gpt->secsz; - return 0; - } - if ((*p == 'b' || *p == 'B') && p[1] == '\0') { - *size = sectors; - return 0; - } - if (dehumanize_number(optarg, &human_num) < 0) - return -1; - *size = human_num; return 0; default: return -1; @@ -1142,3 +1144,28 @@ gpt_entry_get(u_int *entry) return -1; return 0; } +int +gpt_uuid_get(gpt_t gpt, gpt_uuid_t *uuid) +{ + if (!gpt_uuid_is_nil(*uuid)) + return -1; + if (gpt_uuid_parse(optarg, *uuid) != 0) { + gpt_warn(gpt, "Can't parse uuid"); + return -1; + } + return 0; +} + +int +gpt_name_get(gpt_t gpt, void *v) +{ + char **name = v; + if (*name != NULL) + return -1; + *name = strdup(optarg); + if (*name == NULL) { + gpt_warn(gpt, "Can't copy string"); + return -1; + } + return 0; +} diff --git a/sbin/gpt/gpt.h b/sbin/gpt/gpt.h index 8697d53e0b81..50d3a1272862 100644 --- a/sbin/gpt/gpt.h +++ b/sbin/gpt/gpt.h @@ -121,5 +121,8 @@ off_t gpt_check_ais(gpt_t, off_t, u_int, off_t); int gpt_attr_get(uint64_t *); int gpt_attr_update(gpt_t, u_int, uint64_t, uint64_t); int gpt_entry_get(u_int *); +int gpt_human_get(off_t *); +int gpt_uuid_get(gpt_t, gpt_uuid_t *); +int gpt_name_get(gpt_t, void *); #endif /* _GPT_H_ */ diff --git a/sbin/gpt/gpt_uuid.c b/sbin/gpt/gpt_uuid.c index 93560fcf0b36..27e033e3ae59 100644 --- a/sbin/gpt/gpt_uuid.c +++ b/sbin/gpt/gpt_uuid.c @@ -1,4 +1,4 @@ -/* $NetBSD: gpt_uuid.c,v 1.10 2014/12/06 12:24:22 mlelstv Exp $ */ +/* $NetBSD: gpt_uuid.c,v 1.11 2015/12/01 23:29:07 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #include #ifdef __RCSID -__RCSID("$NetBSD: gpt_uuid.c,v 1.10 2014/12/06 12:24:22 mlelstv Exp $"); +__RCSID("$NetBSD: gpt_uuid.c,v 1.11 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -238,8 +238,8 @@ gpt_uuid_create(gpt_type_t t, gpt_uuid_t u, uint16_t *b, size_t s) utf8_to_utf16((const uint8_t *)gpt_nv[t].d, b, s / sizeof(*b)); } -void -gpt_uuid_generate(gpt_uuid_t t) +int +gpt_uuid_generate(gpt_t gpt, gpt_uuid_t t) { struct dce_uuid u; int fd; @@ -249,16 +249,24 @@ gpt_uuid_generate(gpt_uuid_t t) /* Randomly generate the content. */ fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); - if (fd == -1) - err(1, "open(/dev/urandom)"); + if (fd == -1) { + gpt_warn(gpt, "Can't open `/dev/urandom'"); + return -1; + } for (p = (void *)&u, n = sizeof u; 0 < n; p += nread, n -= nread) { nread = read(fd, p, n); - if (nread < 0) - err(1, "read(/dev/urandom)"); - if (nread == 0) - errx(1, "EOF from /dev/urandom"); - if ((size_t)nread > n) - errx(1, "read too much: %zd > %zu", nread, n); + if (nread < 0) { + gpt_warn(gpt, "Can't read `/dev/urandom'"); + goto out; + } + if (nread == 0) { + gpt_warn(gpt, "EOF from /dev/urandom"); + goto out; + } + if ((size_t)nread > n) { + gpt_warnx(gpt, "read too much: %zd > %zu", nread, n); + goto out; + } } (void)close(fd); @@ -271,4 +279,8 @@ gpt_uuid_generate(gpt_uuid_t t) u.clock_seq_hi_and_reserved |= 0x80; gpt_dce_to_uuid(&u, t); + close(fd); + return 0; +out: + return -1; } diff --git a/sbin/gpt/gpt_uuid.h b/sbin/gpt/gpt_uuid.h index 3e15ea576b82..d468742f92bb 100644 --- a/sbin/gpt/gpt_uuid.h +++ b/sbin/gpt/gpt_uuid.h @@ -94,7 +94,8 @@ void gpt_uuid_create(gpt_type_t, gpt_uuid_t, uint16_t *, size_t); int gpt_uuid_parse(const char *, gpt_uuid_t); -void gpt_uuid_generate(gpt_uuid_t); +struct gpt; +int gpt_uuid_generate(struct gpt *, gpt_uuid_t); __END_DECLS diff --git a/sbin/gpt/label.c b/sbin/gpt/label.c index 1e3d33ea9e59..2f140a799524 100644 --- a/sbin/gpt/label.c +++ b/sbin/gpt/label.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: label.c,v 1.22 2015/12/01 19:25:24 christos Exp $"); +__RCSID("$NetBSD: label.c,v 1.23 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -73,33 +73,46 @@ change(struct gpt_ent *ent, void *v) utf8_to_utf16(name, ent->ent_name, 36); } -static char * -name_from_file(const char *fn) +static int +name_from_file(gpt_t gpt, void *v) { FILE *f; char *p; size_t maxlen = 1024; size_t len; - char *name; + const char *fn = optarg; + char **name = v; + + if (*name != NULL) + return -1; if (strcmp(fn, "-") != 0) { f = fopen(fn, "r"); - if (f == NULL) - err(1, "unable to open file %s", fn); + if (f == NULL) { + gpt_warn(gpt, "Can't open `%s'", fn); + return -1; + } } else f = stdin; - name = malloc(maxlen); - len = fread(name, 1, maxlen - 1, f); - if (ferror(f)) - err(1, "unable to read label from file %s", fn); + + if ((*name = malloc(maxlen)) == NULL) { + gpt_warn(gpt, "Can't copy string"); + return -1; + } + len = fread(*name, 1, maxlen - 1, f); + if (ferror(f)) { + free(*name); + gpt_warn(gpt, "Can't label from `%s'", fn); + return -1; + } if (f != stdin) fclose(f); - name[len] = '\0'; + (*name)[len] = '\0'; /* Only keep the first line, excluding the newline character. */ - p = strchr((const char *)name, '\n'); + p = strchr(*name, '\n'); if (p != NULL) *p = '\0'; - return name; + return 0; } static int @@ -116,14 +129,12 @@ cmd_label(gpt_t gpt, int argc, char *argv[]) while ((ch = getopt(argc, argv, GPT_FIND "f:l:")) != -1) { switch(ch) { case 'f': - if (name != NULL) + if (name_from_file(gpt, &name) == -1) return usage(); - name = name_from_file(optarg); break; case 'l': - if (name != NULL) + if (gpt_name_get(gpt, &name) == -1) return usage(); - name = strdup(optarg); break; default: if (gpt_add_find(gpt, &find, ch) == -1) diff --git a/sbin/gpt/show.c b/sbin/gpt/show.c index 26ef7d301e2d..1fdce411ff0e 100644 --- a/sbin/gpt/show.c +++ b/sbin/gpt/show.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: show.c,v 1.25 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: show.c,v 1.26 2015/12/01 23:29:07 christos Exp $"); #endif #include @@ -237,7 +237,6 @@ show_one(gpt_t gpt) static int cmd_show(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; while ((ch = getopt(argc, argv, "gi:lu")) != -1) { @@ -246,10 +245,7 @@ cmd_show(gpt_t gpt, int argc, char *argv[]) show_guid = 1; break; case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) + if (gpt_entry_get(&entry) == -1) return usage(); break; case 'l':