1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10#include <sys/cdefs.h> 11__FBSDID("$FreeBSD$"); 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <unistd.h> 16#include <string.h> 17#include <ctype.h> 18#include <fcntl.h> 19#include <stdarg.h> 20#include <sys/param.h> 21#include <sys/disklabel.h> 22#ifdef PC98 23#include <sys/diskpc98.h> 24#else 25#include <sys/diskmbr.h> 26#endif 27#include <sys/mount.h> 28#include <sys/stat.h> 29#include <sys/sysctl.h> 30#include <grp.h> 31#include <paths.h> 32#include <pwd.h> 33#include "libdisk.h" 34 35static int 36Fixup_FreeBSD_Names(struct chunk *c) 37{ 38 struct chunk *c1, *c3; 39 uint j; 40 41 if (!strcmp(c->name, "X")) 42 return 0; 43 44 /* reset all names to "X" */ 45 for (c1 = c->part; c1; c1 = c1->next) { 46 c1->oname = c1->name; 47 c1->name = malloc(12); 48 if (!c1->name) 49 return -1; 50 strcpy(c1->name,"X"); 51 } 52 53 /* Allocate the first swap-partition we find */ 54 for (c1 = c->part; c1; c1 = c1->next) { 55 if (c1->type == unused) 56 continue; 57 if (c1->subtype != FS_SWAP) 58 continue; 59 sprintf(c1->name, "%s%c", c->name, SWAP_PART + 'a'); 60 break; 61 } 62 63 /* Allocate the first root-partition we find */ 64 for (c1 = c->part; c1; c1 = c1->next) { 65 if (c1->type == unused) 66 continue; 67 if (!(c1->flags & CHUNK_IS_ROOT)) 68 continue; 69 sprintf(c1->name, "%s%c", c->name, 0 + 'a'); 70 break; 71 } 72 73 /* Try to give them the same as they had before */ 74 for (c1 = c->part; c1; c1 = c1->next) { 75 if (strcmp(c1->name, "X")) 76 continue; 77 for (c3 = c->part; c3 ; c3 = c3->next) 78 if (c1 != c3 && !strcmp(c3->name, c1->oname)) 79 goto newname; 80 strcpy(c1->name, c1->oname); 81 newname: 82 ; 83 } 84 85 /* Allocate the rest sequentially */ 86 for (c1 = c->part; c1; c1 = c1->next) { 87 const char order[] = "defghab"; 88 89 if (c1->type == unused) 90 continue; 91 if (strcmp("X", c1->name)) 92 continue; 93 94 for (j = 0; j < strlen(order); j++) { 95 sprintf(c1->name, "%s%c", c->name, order[j]); 96 for (c3 = c->part; c3 ; c3 = c3->next) 97 if (c1 != c3 && !strcmp(c3->name, c1->name)) 98 goto match; 99 break; 100 match: 101 strcpy(c1->name, "X"); 102 continue; 103 } 104 } 105 for (c1 = c->part; c1; c1 = c1->next) { 106 free(c1->oname); 107 c1->oname = 0; 108 } 109 return 0; 110} 111 112#ifndef PC98 113static int 114Fixup_Extended_Names(struct chunk *c) 115{ 116 struct chunk *c1; 117 int j = 5; 118 119 for (c1 = c->part; c1; c1 = c1->next) { 120 if (c1->type == unused) 121 continue; 122 free(c1->name); 123 c1->name = malloc(12); 124 if (!c1->name) 125 return -1; 126 sprintf(c1->name, "%ss%d", c->disk->chunks->name, j++); 127 if (c1->type == freebsd) 128 if (Fixup_FreeBSD_Names(c1) != 0) 129 return -1; 130 } 131 return 0; 132} 133#endif 134 135#ifdef __powerpc__ 136static int 137Fixup_Apple_Names(struct chunk *c) 138{ 139 struct chunk *c1; 140 141 for (c1 = c->part; c1; c1 = c1->next) { 142 if (c1->type == unused) 143 continue; 144 free(c1->name); 145 c1->name = strdup(c->name); 146 if (!c1->name) 147 return (-1); 148 } 149 return 0; 150} 151#endif 152 153int 154Fixup_Names(struct disk *d) 155{ 156 struct chunk *c1, *c2; 157#if defined(__i386__) || defined(__ia64__) || defined(__amd64__) 158 struct chunk *c3; 159 int j, max; 160#endif 161 162 c1 = d->chunks; 163 for (c2 = c1->part; c2 ; c2 = c2->next) { 164 if (c2->type == unused) 165 continue; 166 if (strcmp(c2->name, "X")) 167 continue; 168#if defined(__i386__) || defined(__ia64__) || defined(__amd64__) 169 c2->oname = malloc(12); 170 if (!c2->oname) 171 return -1; 172#ifdef __ia64__ 173 max = d->gpt_size; 174#else 175 max = NDOSPART; 176#endif 177 for (j = 1; j <= max; j++) { 178#ifdef __ia64__ 179 sprintf(c2->oname, "%s%c%d", c1->name, 180 (c1->type == whole) ? 'p' : 's', j); 181#else 182 sprintf(c2->oname, "%ss%d", c1->name, j); 183#endif 184 for (c3 = c1->part; c3; c3 = c3->next) 185 if (c3 != c2 && !strcmp(c3->name, c2->oname)) 186 goto match; 187 free(c2->name); 188 c2->name = c2->oname; 189 c2->oname = 0; 190 break; 191 match: 192 continue; 193 } 194 if (c2->oname) 195 free(c2->oname); 196#else 197 free(c2->name); 198 c2->name = strdup(c1->name); 199#endif /*__i386__*/ 200 } 201 for (c2 = c1->part; c2; c2 = c2->next) { 202 if (c2->type == freebsd) 203 Fixup_FreeBSD_Names(c2); 204#ifdef __powerpc__ 205 else if (c2->type == apple) 206 Fixup_Apple_Names(c2); 207#endif 208#ifndef PC98 209 else if (c2->type == extended) 210 Fixup_Extended_Names(c2); 211#endif 212 } 213 return 0; 214} 215 216int 217Create_Chunk(struct disk *d, daddr_t offset, daddr_t size, chunk_e type, 218 int subtype, u_long flags, const char *sname) 219{ 220 int i; 221 222#ifndef __ia64__ 223 if (!(flags & CHUNK_FORCE_ALL)) { 224 daddr_t l; 225#ifdef PC98 226 /* Never use the first cylinder */ 227 if (!offset) { 228 offset += (d->bios_sect * d->bios_hd); 229 size -= (d->bios_sect * d->bios_hd); 230 } 231#else 232 /* Never use the first track */ 233 if (!offset) { 234 offset += d->bios_sect; 235 size -= d->bios_sect; 236 } 237#endif /* PC98 */ 238 239 /* Always end on cylinder boundary */ 240 l = (offset + size) % (d->bios_sect * d->bios_hd); 241 size -= l; 242 } 243#endif 244 245 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, sname); 246 Fixup_Names(d); 247 return i; 248} 249 250struct chunk * 251Create_Chunk_DWIM(struct disk *d, struct chunk *parent, daddr_t size, 252 chunk_e type, int subtype, u_long flags) 253{ 254 int i; 255 struct chunk *c1; 256 daddr_t offset; 257 258 if (!parent) 259 parent = d->chunks; 260 261 if ((parent->type == freebsd && type == part && parent->part == NULL) 262 || (parent->type == apple && type == part && parent->part == NULL)) { 263 c1 = New_Chunk(); 264 if (c1 == NULL) 265 return (NULL); 266 c1->disk = parent->disk; 267 c1->offset = parent->offset; 268 c1->size = parent->size; 269 c1->end = parent->offset + parent->size - 1; 270 c1->type = unused; 271 if (parent->sname != NULL) 272 c1->sname = strdup(parent->sname); 273 c1->name = strdup("-"); 274 parent->part = c1; 275 } 276 277 for (c1 = parent->part; c1; c1 = c1->next) { 278 if (c1->type != unused) 279 continue; 280 if (c1->size < size) 281 continue; 282 offset = c1->offset; 283 goto found; 284 } 285 return 0; 286found: 287 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, "-"); 288 if (i) 289 return 0; 290 Fixup_Names(d); 291 for (c1 = parent->part; c1; c1 = c1->next) 292 if (c1->offset == offset) 293 return c1; 294 /* barfout(1, "Serious internal trouble"); */ 295 return 0; 296} 297