1 1.1 jnemeth /*- 2 1.1 jnemeth * Copyright (c) 2002 Marcel Moolenaar 3 1.1 jnemeth * All rights reserved. 4 1.1 jnemeth * 5 1.1 jnemeth * Redistribution and use in source and binary forms, with or without 6 1.1 jnemeth * modification, are permitted provided that the following conditions 7 1.1 jnemeth * are met: 8 1.1 jnemeth * 9 1.1 jnemeth * 1. Redistributions of source code must retain the above copyright 10 1.1 jnemeth * notice, this list of conditions and the following disclaimer. 11 1.1 jnemeth * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 jnemeth * notice, this list of conditions and the following disclaimer in the 13 1.1 jnemeth * documentation and/or other materials provided with the distribution. 14 1.1 jnemeth * 15 1.1 jnemeth * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 jnemeth * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 jnemeth * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 jnemeth * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 jnemeth * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 jnemeth * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 jnemeth * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 jnemeth * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 jnemeth * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 jnemeth * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 jnemeth */ 26 1.1 jnemeth 27 1.9 christos #if HAVE_NBTOOL_CONFIG_H 28 1.9 christos #include "nbtool_config.h" 29 1.9 christos #endif 30 1.9 christos 31 1.1 jnemeth #include <sys/cdefs.h> 32 1.1 jnemeth #ifdef __FBSDID 33 1.1 jnemeth __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); 34 1.1 jnemeth #endif 35 1.1 jnemeth #ifdef __RCSID 36 1.26 christos __RCSID("$NetBSD: resize.c,v 1.26 2025/02/23 20:47:19 christos Exp $"); 37 1.1 jnemeth #endif 38 1.1 jnemeth 39 1.1 jnemeth #include <sys/types.h> 40 1.1 jnemeth 41 1.1 jnemeth #include <err.h> 42 1.25 jmcneill #include <stdbool.h> 43 1.1 jnemeth #include <stddef.h> 44 1.1 jnemeth #include <stdio.h> 45 1.1 jnemeth #include <stdlib.h> 46 1.1 jnemeth #include <string.h> 47 1.1 jnemeth #include <unistd.h> 48 1.1 jnemeth 49 1.1 jnemeth #include "map.h" 50 1.1 jnemeth #include "gpt.h" 51 1.15 christos #include "gpt_private.h" 52 1.1 jnemeth 53 1.16 christos static int cmd_resize(gpt_t, int, char *[]); 54 1.1 jnemeth 55 1.16 christos static const char *resizehelp[] = { 56 1.25 jmcneill "[-i index | -b blocknr] [-a alignment] [-s size] [-q]", 57 1.16 christos }; 58 1.16 christos 59 1.26 christos const struct gpt_cmd c_resize = { 60 1.16 christos "resize", 61 1.16 christos cmd_resize, 62 1.16 christos resizehelp, __arraycount(resizehelp), 63 1.23 jnemeth GPT_SYNC, 64 1.16 christos }; 65 1.1 jnemeth 66 1.16 christos #define usage() gpt_usage(NULL, &c_resize) 67 1.1 jnemeth 68 1.15 christos static int 69 1.26 christos resize(gpt_t gpt, u_int entry, off_t alignment, off_t sectors, 70 1.26 christos off_t size __unused, bool quiet) 71 1.1 jnemeth { 72 1.15 christos map_t map; 73 1.1 jnemeth struct gpt_ent *ent; 74 1.1 jnemeth unsigned int i; 75 1.25 jmcneill off_t alignsecs, newsize, oldsize; 76 1.21 christos uint64_t end; 77 1.1 jnemeth 78 1.1 jnemeth 79 1.26 christos if (gpt_hdr(gpt) == NULL) 80 1.15 christos return -1; 81 1.15 christos 82 1.1 jnemeth i = entry - 1; 83 1.15 christos ent = gpt_ent_primary(gpt, i); 84 1.11 christos if (gpt_uuid_is_nil(ent->ent_type)) { 85 1.15 christos gpt_warnx(gpt, "Entry at index %u is unused", entry); 86 1.15 christos return -1; 87 1.1 jnemeth } 88 1.1 jnemeth 89 1.15 christos alignsecs = alignment / gpt->secsz; 90 1.1 jnemeth 91 1.15 christos for (map = map_first(gpt); map != NULL; map = map->map_next) { 92 1.1 jnemeth if (entry == map->map_index) 93 1.1 jnemeth break; 94 1.1 jnemeth } 95 1.4 christos if (map == NULL) { 96 1.15 christos gpt_warnx(gpt, "Could not find map entry corresponding " 97 1.15 christos "to index"); 98 1.15 christos return -1; 99 1.1 jnemeth } 100 1.1 jnemeth 101 1.7 jnemeth if (sectors > 0 && sectors == map->map_size) 102 1.1 jnemeth if (alignment == 0 || 103 1.7 jnemeth (alignment > 0 && sectors % alignsecs == 0)) { 104 1.1 jnemeth /* nothing to do */ 105 1.25 jmcneill if (!quiet) 106 1.25 jmcneill gpt_warnx(gpt, 107 1.25 jmcneill "partition does not need resizing"); 108 1.15 christos return 0; 109 1.1 jnemeth } 110 1.1 jnemeth 111 1.25 jmcneill oldsize = map->map_size; 112 1.15 christos newsize = map_resize(gpt, map, sectors, alignsecs); 113 1.18 christos if (newsize == -1) 114 1.15 christos return -1; 115 1.1 jnemeth 116 1.25 jmcneill if (oldsize == newsize) { 117 1.25 jmcneill /* Nothing to do */ 118 1.25 jmcneill if (!quiet) 119 1.25 jmcneill gpt_warnx(gpt, 120 1.25 jmcneill "partition does not need resizing"); 121 1.25 jmcneill return 0; 122 1.25 jmcneill } 123 1.25 jmcneill 124 1.21 christos end = htole64((uint64_t)(map->map_start + newsize - 1LL)); 125 1.21 christos ent->ent_lba_end = end; 126 1.1 jnemeth 127 1.15 christos if (gpt_write_primary(gpt) == -1) 128 1.15 christos return -1; 129 1.1 jnemeth 130 1.15 christos ent = gpt_ent(gpt->gpt, gpt->lbt, i); 131 1.21 christos ent->ent_lba_end = end; 132 1.1 jnemeth 133 1.15 christos if (gpt_write_backup(gpt) == -1) 134 1.15 christos return -1; 135 1.1 jnemeth 136 1.22 christos gpt_msg(gpt, "Partition %d resized: %" PRIu64 " %" PRIu64, entry, 137 1.15 christos map->map_start, newsize); 138 1.1 jnemeth 139 1.15 christos return 0; 140 1.1 jnemeth } 141 1.1 jnemeth 142 1.16 christos static int 143 1.15 christos cmd_resize(gpt_t gpt, int argc, char *argv[]) 144 1.1 jnemeth { 145 1.15 christos int ch; 146 1.24 martin off_t alignment = 0, sectors, start = 0, size = 0; 147 1.19 christos unsigned int entry = 0; 148 1.24 martin map_t m; 149 1.25 jmcneill bool quiet = false; 150 1.1 jnemeth 151 1.25 jmcneill while ((ch = getopt(argc, argv, GPT_AIS "b:q")) != -1) { 152 1.24 martin if (ch == 'b') 153 1.24 martin gpt_human_get(gpt, &start); 154 1.25 jmcneill else if (ch == 'q') 155 1.25 jmcneill quiet = true; 156 1.24 martin else if (gpt_add_ais(gpt, &alignment, &entry, &size, ch) == -1) 157 1.16 christos return usage(); 158 1.1 jnemeth } 159 1.1 jnemeth 160 1.15 christos if (argc != optind) 161 1.16 christos return usage(); 162 1.1 jnemeth 163 1.24 martin if (start > 0) { 164 1.24 martin for (m = map_first(gpt); m != NULL; m = m->map_next) { 165 1.24 martin if (m->map_type != MAP_TYPE_GPT_PART || 166 1.24 martin m->map_index < 1) 167 1.24 martin continue; 168 1.24 martin if (start != m->map_start) 169 1.24 martin continue; 170 1.24 martin entry = m->map_index; 171 1.24 martin break; 172 1.24 martin } 173 1.24 martin } 174 1.24 martin 175 1.17 christos if ((sectors = gpt_check_ais(gpt, alignment, entry, size)) == -1) 176 1.15 christos return -1; 177 1.1 jnemeth 178 1.25 jmcneill return resize(gpt, entry, alignment, sectors, size, quiet); 179 1.1 jnemeth } 180