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 27 #if HAVE_NBTOOL_CONFIG_H 28 #include "nbtool_config.h" 29 #endif 30 31 #include <sys/cdefs.h> 32 #ifdef __FBSDID 33 __FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $"); 34 #endif 35 #ifdef __RCSID 36 __RCSID("$NetBSD: create.c,v 1.26 2025/12/17 16:18:11 nia Exp $"); 37 #endif 38 39 #include <sys/types.h> 40 #if defined(HAVE_SYS_ENDIAN_H) || ! defined(HAVE_NBTOOL_CONFIG_H) 41 #include <sys/endian.h> 42 #endif 43 #include <sys/stat.h> 44 #include <sys/bootblock.h> 45 46 #include <err.h> 47 #include <stddef.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 53 #include "map.h" 54 #include "gpt.h" 55 #include "gpt_private.h" 56 57 static int cmd_create(gpt_t, int, char *[]); 58 59 static const char *createhelp[] = { 60 "[-AfP] [-p partitions]", 61 }; 62 63 const struct gpt_cmd c_create = { 64 "create", 65 cmd_create, 66 createhelp, __arraycount(createhelp), 67 0, 68 }; 69 70 #define usage() gpt_usage(NULL, &c_create) 71 72 73 static int 74 create(gpt_t gpt, u_int parts, int force, int primary_only, int active) 75 { 76 off_t last = gpt_last(gpt); 77 map_t map; 78 struct mbr *mbr; 79 80 map = map_find(gpt, MAP_TYPE_MBR); 81 if (map != NULL) { 82 if (!force) { 83 gpt_warnx(gpt, "Device contains a MBR"); 84 return -1; 85 } 86 /* Nuke the MBR in our internal map. */ 87 map->map_type = MAP_TYPE_UNUSED; 88 } 89 90 /* 91 * Create PMBR. 92 */ 93 if (map_find(gpt, MAP_TYPE_PMBR) == NULL) { 94 if (map_free(gpt, 0LL, 1LL) == 0) { 95 gpt_warnx(gpt, "No room for the PMBR"); 96 return -1; 97 } 98 mbr = gpt_read(gpt, 0LL, 1); 99 if (mbr == NULL) { 100 gpt_warnx(gpt, "Error reading MBR"); 101 return -1; 102 } 103 memset(mbr, 0, sizeof(*mbr)); 104 mbr->mbr_sig = htole16(MBR_SIG); 105 gpt_create_pmbr_part(mbr->mbr_part, last, active); 106 107 map = map_add(gpt, 0LL, 1LL, MAP_TYPE_PMBR, mbr, 1); 108 if (gpt_write(gpt, map) == -1) { 109 gpt_warn(gpt, "Can't write PMBR"); 110 return -1; 111 } 112 } 113 114 if (gpt_create(gpt, last, parts, primary_only) == -1) 115 return -1; 116 117 if (gpt_write_primary(gpt) == -1) 118 return -1; 119 120 if (!primary_only && gpt_write_backup(gpt) == -1) 121 return -1; 122 123 return 0; 124 } 125 126 static int 127 cmd_create(gpt_t gpt, int argc, char *argv[]) 128 { 129 int ch; 130 int active = 0; 131 int force = 0; 132 int primary_only = 0; 133 u_int parts = 0; 134 135 while ((ch = getopt(argc, argv, "AfPp:")) != -1) { 136 switch(ch) { 137 case 'A': 138 active = 1; 139 break; 140 case 'f': 141 force = 1; 142 break; 143 case 'P': 144 primary_only = 1; 145 break; 146 case 'p': 147 if (gpt_uint_get(gpt, &parts) == -1) 148 return -1; 149 break; 150 default: 151 return usage(); 152 } 153 } 154 if (parts == 0) 155 parts = 128; 156 157 if (argc != optind) 158 return usage(); 159 160 return create(gpt, parts, force, primary_only, active); 161 } 162