Annotation of src/sbin/gpt/add.c, Revision 1.37
1.1 christos 1: /*-
2: * Copyright (c) 2002 Marcel Moolenaar
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
1.25 christos 27: #if HAVE_NBTOOL_CONFIG_H
28: #include "nbtool_config.h"
29: #endif
30:
1.1 christos 31: #include <sys/cdefs.h>
1.2 christos 32: #ifdef __FBSDID
33: __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
34: #endif
35: #ifdef __RCSID
1.37 ! jnemeth 36: __RCSID("$NetBSD: add.c,v 1.36 2015/12/02 04:07:11 christos Exp $");
1.2 christos 37: #endif
1.1 christos 38:
39: #include <sys/types.h>
1.31 christos 40: #include <sys/param.h>
41: #include <sys/stat.h>
1.1 christos 42:
43: #include <err.h>
44: #include <stddef.h>
45: #include <stdio.h>
46: #include <stdlib.h>
47: #include <string.h>
48: #include <unistd.h>
49:
50: #include "map.h"
51: #include "gpt.h"
1.31 christos 52: #include "gpt_private.h"
1.1 christos 53:
1.27 christos 54: static gpt_uuid_t type;
1.23 jnemeth 55: static off_t alignment, block, sectors, size;
1.1 christos 56: static unsigned int entry;
1.15 jnemeth 57: static uint8_t *name;
1.32 christos 58: static int cmd_add(gpt_t, int, char *[]);
1.1 christos 59:
1.32 christos 60: static const char *addhelp[] = {
61: "[-a alignment] [-b blocknr] [-i index] [-l label]",
62: "[-s size] [-t type]",
63: };
64:
65: struct gpt_cmd c_add = {
66: "add",
67: cmd_add,
68: addhelp, __arraycount(addhelp),
69: 0,
70: };
1.5 riz 71:
1.32 christos 72: #define usage() gpt_usage(NULL, &c_add)
1.1 christos 73:
1.35 christos 74: static void
75: ent_set(struct gpt_ent *ent, const map_t map, const gpt_uuid_t xtype,
76: const uint8_t *xname)
77: {
78: gpt_uuid_copy(ent->ent_type, xtype);
79: ent->ent_lba_start = htole64(map->map_start);
80: ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
1.36 christos 81: if (xname == NULL)
82: return;
83: utf8_to_utf16(xname, ent->ent_name, __arraycount(ent->ent_name));
1.35 christos 84: }
85:
1.31 christos 86: static int
87: add(gpt_t gpt)
1.1 christos 88: {
1.31 christos 89: map_t map;
1.1 christos 90: struct gpt_hdr *hdr;
1.35 christos 91: struct gpt_ent *ent;
1.1 christos 92: unsigned int i;
1.15 jnemeth 93: off_t alignsecs;
1.33 christos 94: char buf[128];
1.15 jnemeth 95:
1.31 christos 96: if ((hdr = gpt_hdr(gpt)) == NULL)
97: return -1;
1.1 christos 98:
1.3 he 99: ent = NULL;
1.1 christos 100:
101: if (entry > le32toh(hdr->hdr_entries)) {
1.31 christos 102: gpt_warnx(gpt, "index %u out of range (%u max)",
1.1 christos 103: entry, le32toh(hdr->hdr_entries));
1.31 christos 104: return -1;
1.1 christos 105: }
106:
107: if (entry > 0) {
108: i = entry - 1;
1.31 christos 109: ent = gpt_ent_primary(gpt, i);
1.27 christos 110: if (!gpt_uuid_is_nil(ent->ent_type)) {
1.31 christos 111: gpt_warnx(gpt, "Entry at index %u is not free", entry);
112: return -1;
1.1 christos 113: }
114: } else {
115: /* Find empty slot in GPT table. */
116: for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
1.31 christos 117: ent = gpt_ent_primary(gpt, i);
1.27 christos 118: if (gpt_uuid_is_nil(ent->ent_type))
1.1 christos 119: break;
120: }
121: if (i == le32toh(hdr->hdr_entries)) {
1.31 christos 122: gpt_warnx(gpt, "No available table entries");
123: return -1;
1.1 christos 124: }
125: }
126:
1.15 jnemeth 127: if (alignment > 0) {
1.31 christos 128: alignsecs = alignment / gpt->secsz;
129: map = map_alloc(gpt, block, sectors, alignsecs);
1.15 jnemeth 130: if (map == NULL) {
1.31 christos 131: gpt_warnx(gpt, "Not enough space available on "
132: "device for an aligned partition");
133: return -1;
1.15 jnemeth 134: }
135: } else {
1.31 christos 136: map = map_alloc(gpt, block, sectors, 0);
1.15 jnemeth 137: if (map == NULL) {
1.31 christos 138: gpt_warnx(gpt, "Not enough space available on device");
139: return -1;
1.15 jnemeth 140: }
1.1 christos 141: }
142:
1.35 christos 143: ent_set(ent, map, type, name);
1.31 christos 144: gpt_write_primary(gpt);
1.1 christos 145:
1.31 christos 146: ent = gpt_ent_backup(gpt, i);
1.35 christos 147: ent_set(ent, map, type, name);
1.31 christos 148: gpt_write_backup(gpt);
1.1 christos 149:
1.33 christos 150: gpt_uuid_snprintf(buf, sizeof(buf), "%d", type);
151: gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64, i + 1,
152: buf, map->map_start, map->map_size);
1.31 christos 153: return 0;
1.1 christos 154: }
155:
1.32 christos 156: static int
1.31 christos 157: cmd_add(gpt_t gpt, int argc, char *argv[])
1.1 christos 158: {
1.31 christos 159: int ch;
1.1 christos 160:
1.37 ! jnemeth 161: while ((ch = getopt(argc, argv, GPT_AIS "b:l:t:")) != -1) {
1.1 christos 162: switch(ch) {
163: case 'b':
1.34 christos 164: if (gpt_human_get(&block) == -1)
1.32 christos 165: return usage();
1.1 christos 166: break;
1.15 jnemeth 167: case 'l':
1.34 christos 168: if (gpt_name_get(gpt, &name) == -1)
1.32 christos 169: return usage();
1.15 jnemeth 170: break;
1.1 christos 171: case 't':
1.34 christos 172: if (gpt_uuid_get(gpt, &type) == -1)
1.32 christos 173: return usage();
1.1 christos 174: break;
175: default:
1.33 christos 176: if (gpt_add_ais(gpt, &alignment, &entry, &size, ch)
177: == -1)
178: return usage();
179: break;
1.1 christos 180: }
181: }
182:
1.33 christos 183: if (argc != optind)
1.32 christos 184: return usage();
1.1 christos 185:
1.9 jakllsch 186: /* Create NetBSD FFS partitions by default. */
1.34 christos 187: if (gpt_uuid_is_nil(type))
1.27 christos 188: gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0);
1.1 christos 189:
1.31 christos 190: if (optind != argc)
1.32 christos 191: return usage();
1.1 christos 192:
1.35 christos 193: if ((sectors = gpt_check_ais(gpt, alignment, ~0, size)) == -1)
1.31 christos 194: return -1;
1.1 christos 195:
1.31 christos 196: return add(gpt);
1.1 christos 197: }
CVSweb <webmaster@jp.NetBSD.org>