Annotation of src/sbin/gpt/add.c, Revision 1.38
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.38 ! christos 36: __RCSID("$NetBSD: add.c,v 1.37 2015/12/02 11:20:34 jnemeth 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.32 christos 54: static int cmd_add(gpt_t, int, char *[]);
1.1 christos 55:
1.32 christos 56: static const char *addhelp[] = {
1.38 ! christos 57: "[-a alignment] [-b blocknr] [-i index] [-l label]",
! 58: "[-s size] [-t type]",
1.32 christos 59: };
60:
61: struct gpt_cmd c_add = {
62: "add",
63: cmd_add,
64: addhelp, __arraycount(addhelp),
65: 0,
66: };
1.5 riz 67:
1.32 christos 68: #define usage() gpt_usage(NULL, &c_add)
1.1 christos 69:
1.35 christos 70: static void
71: ent_set(struct gpt_ent *ent, const map_t map, const gpt_uuid_t xtype,
72: const uint8_t *xname)
73: {
74: gpt_uuid_copy(ent->ent_type, xtype);
75: ent->ent_lba_start = htole64(map->map_start);
76: ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
1.36 christos 77: if (xname == NULL)
78: return;
79: utf8_to_utf16(xname, ent->ent_name, __arraycount(ent->ent_name));
1.35 christos 80: }
81:
1.31 christos 82: static int
1.38 ! christos 83: add(gpt_t gpt, off_t alignment, off_t block, off_t sectors, off_t size,
! 84: u_int entry, uint8_t *name, gpt_uuid_t type)
1.1 christos 85: {
1.31 christos 86: map_t map;
1.1 christos 87: struct gpt_hdr *hdr;
1.35 christos 88: struct gpt_ent *ent;
1.1 christos 89: unsigned int i;
1.15 jnemeth 90: off_t alignsecs;
1.33 christos 91: char buf[128];
1.15 jnemeth 92:
1.31 christos 93: if ((hdr = gpt_hdr(gpt)) == NULL)
94: return -1;
1.1 christos 95:
1.3 he 96: ent = NULL;
1.1 christos 97:
98: if (entry > le32toh(hdr->hdr_entries)) {
1.31 christos 99: gpt_warnx(gpt, "index %u out of range (%u max)",
1.1 christos 100: entry, le32toh(hdr->hdr_entries));
1.31 christos 101: return -1;
1.1 christos 102: }
103:
104: if (entry > 0) {
105: i = entry - 1;
1.31 christos 106: ent = gpt_ent_primary(gpt, i);
1.27 christos 107: if (!gpt_uuid_is_nil(ent->ent_type)) {
1.31 christos 108: gpt_warnx(gpt, "Entry at index %u is not free", entry);
109: return -1;
1.1 christos 110: }
111: } else {
112: /* Find empty slot in GPT table. */
113: for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
1.31 christos 114: ent = gpt_ent_primary(gpt, i);
1.27 christos 115: if (gpt_uuid_is_nil(ent->ent_type))
1.1 christos 116: break;
117: }
118: if (i == le32toh(hdr->hdr_entries)) {
1.31 christos 119: gpt_warnx(gpt, "No available table entries");
120: return -1;
1.1 christos 121: }
122: }
123:
1.15 jnemeth 124: if (alignment > 0) {
1.31 christos 125: alignsecs = alignment / gpt->secsz;
126: map = map_alloc(gpt, block, sectors, alignsecs);
1.15 jnemeth 127: if (map == NULL) {
1.31 christos 128: gpt_warnx(gpt, "Not enough space available on "
129: "device for an aligned partition");
130: return -1;
1.15 jnemeth 131: }
132: } else {
1.31 christos 133: map = map_alloc(gpt, block, sectors, 0);
1.15 jnemeth 134: if (map == NULL) {
1.31 christos 135: gpt_warnx(gpt, "Not enough space available on device");
136: return -1;
1.15 jnemeth 137: }
1.1 christos 138: }
139:
1.35 christos 140: ent_set(ent, map, type, name);
1.31 christos 141: gpt_write_primary(gpt);
1.1 christos 142:
1.31 christos 143: ent = gpt_ent_backup(gpt, i);
1.35 christos 144: ent_set(ent, map, type, name);
1.31 christos 145: gpt_write_backup(gpt);
1.1 christos 146:
1.33 christos 147: gpt_uuid_snprintf(buf, sizeof(buf), "%d", type);
148: gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64, i + 1,
149: buf, map->map_start, map->map_size);
1.31 christos 150: return 0;
1.1 christos 151: }
152:
1.32 christos 153: static int
1.31 christos 154: cmd_add(gpt_t gpt, int argc, char *argv[])
1.1 christos 155: {
1.31 christos 156: int ch;
1.38 ! christos 157: off_t alignment = 0, block = 0, sectors = 0, size = 0;
! 158: unsigned int entry = 0;
! 159: uint8_t *name = NULL;
! 160: gpt_uuid_t type;
! 161:
! 162: gpt_uuid_copy(type, gpt_uuid_nil);
1.1 christos 163:
1.37 jnemeth 164: while ((ch = getopt(argc, argv, GPT_AIS "b:l:t:")) != -1) {
1.1 christos 165: switch(ch) {
166: case 'b':
1.34 christos 167: if (gpt_human_get(&block) == -1)
1.32 christos 168: return usage();
1.1 christos 169: break;
1.15 jnemeth 170: case 'l':
1.34 christos 171: if (gpt_name_get(gpt, &name) == -1)
1.32 christos 172: return usage();
1.15 jnemeth 173: break;
1.1 christos 174: case 't':
1.34 christos 175: if (gpt_uuid_get(gpt, &type) == -1)
1.32 christos 176: return usage();
1.1 christos 177: break;
178: default:
1.33 christos 179: if (gpt_add_ais(gpt, &alignment, &entry, &size, ch)
180: == -1)
181: return usage();
182: break;
1.1 christos 183: }
184: }
185:
1.33 christos 186: if (argc != optind)
1.32 christos 187: return usage();
1.1 christos 188:
1.9 jakllsch 189: /* Create NetBSD FFS partitions by default. */
1.34 christos 190: if (gpt_uuid_is_nil(type))
1.27 christos 191: gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0);
1.1 christos 192:
1.31 christos 193: if (optind != argc)
1.32 christos 194: return usage();
1.1 christos 195:
1.35 christos 196: if ((sectors = gpt_check_ais(gpt, alignment, ~0, size)) == -1)
1.31 christos 197: return -1;
1.1 christos 198:
1.38 ! christos 199: return add(gpt, alignment, block, sectors, size, entry, name, type);
1.1 christos 200: }
CVSweb <webmaster@jp.NetBSD.org>