1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.0 (the 'License'). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License." 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24#include <stdio.h> 25#ifndef __linux__ 26#include <stdlib.h> 27#include <unistd.h> 28#endif 29#include <string.h> 30#include <errno.h> 31#include <fcntl.h> 32 33#include "io.h" 34#include "errors.h" 35 36#import "pdisk.h" 37#import "partition_map.h" 38#import "dump.h" 39 40#define CMD_FAIL 1 41#define CMD_SUCCESS 0 42 43#define MIN_PARTITION_SIZE 4 44 45typedef int (*funcPtr_t)(); 46 47typedef struct { 48 char * name; 49 funcPtr_t func; 50 int nargs; 51 char * description; 52} cmdline_option_t; 53 54 55static int block_size(); 56static int create_partition(); 57static int delete_partition(); 58static int disk_is_partitioned(); 59static int initialize(); 60static int our_dump(); 61static int partition_display(); 62static int split_partition(); 63 64cmdline_option_t optionTable[] = { 65 { "-blockSize", block_size, 0, "display the block size used by the map" }, 66 { "-createPartition", create_partition, 0, "create a new partition" }, 67 { "-deletePartition", delete_partition, 0, "delete a partition" }, 68 { "-dump", our_dump, 0, "dump the list of partitions" }, 69 { "-initialize", initialize, 0, "initialize the partition map" }, 70 { "-isDiskPartitioned", disk_is_partitioned, 0, "is the disk partitioned" }, 71 { "-partitionEntry", partition_display, 0, "get the partition name, type, base, and size" }, 72 { "-splitPartition", split_partition, 0, "split an existing partition in two pieces" }, 73 { 0, 0, 0 }, 74}; 75 76static int 77initialize(char * name) 78{ 79 partition_map_header * map; 80 81 map = create_partition_map(name, NULL, O_RDWR); 82 if (map == NULL) 83 return (CMD_FAIL); 84 add_partition_to_map("Apple", kMapType, 85 1, (map->media_size <= 128? 2: 63), map); 86 write_partition_map(map); 87 close_partition_map(map); 88 return (CMD_SUCCESS); 89} 90 91static int 92block_size(char * name) 93{ 94 partition_map_header *map; 95 int junk; 96 97 map = open_partition_map(name, &junk, 0, O_RDONLY); 98 if (map == NULL) { 99 return (CMD_FAIL); 100 } 101 printf("%d\n", map->logical_block); 102 close_partition_map(map); 103 return (CMD_SUCCESS); 104} 105 106static int 107our_dump(char * name) 108{ 109 partition_map_header *map; 110 int junk; 111 112 map = open_partition_map(name, &junk, 0, O_RDONLY); 113 if (map == NULL) { 114 return (CMD_FAIL); 115 } 116 117 dump_partition_map(map, 1); 118 119 close_partition_map(map); 120 return (CMD_SUCCESS); 121} 122 123static int 124disk_is_partitioned(char * name) 125{ 126 partition_map_header *map; 127 int junk; 128 129 map = open_partition_map(name, &junk, 0, O_RDONLY); 130 if (map) { 131 close_partition_map(map); 132 return (CMD_SUCCESS); 133 } 134 return (CMD_FAIL); 135} 136 137static int 138partition_display(char * name, int argc, char * * argv) 139{ 140 partition_map * entry; 141 int junk; 142 int j; 143 partition_map_header * map; 144 int rv = CMD_FAIL; 145 146 if (argc < 2) { 147 fprintf(stderr, "pdisk: %s <partition number>\n", *argv); 148 return (CMD_FAIL); 149 } 150 151 map = open_partition_map(name, &junk, 0, O_RDONLY); 152 if (!map) { 153 fprintf(stderr, "pdisk: disk is not partitioned\n"); 154 return (CMD_FAIL); 155 } 156 j = atoi(argv[1]); 157 entry = find_entry_by_disk_address(j, map); 158 if (!entry) { 159 fprintf(stderr, "pdisk: partition %d does not exist\n", j); 160 } 161 else { 162 DPME * p = entry->data; 163 164 rv = CMD_SUCCESS; 165 166 printf("%s %s %u %u\n", p->dpme_name, p->dpme_type, 167 p->dpme_pblock_start, p->dpme_pblocks); 168 } 169 close_partition_map(map); 170 return (rv); 171} 172 173static int 174split_partition(char * name, int argc, char * * argv) 175{ 176 partition_map * entry; 177 int junk; 178 partition_map_header * map; 179 u32 new_size; 180 int part; 181 int rv = CMD_SUCCESS; 182 char * split_name; 183 char * split_type; 184 185 if (argc < 5) { 186 fprintf(stderr, "pdisk %s <partno> <1st part size> <2nd part name> <2nd part type>\n", 187 argv[0]); 188 return (CMD_FAIL); 189 } 190 map = open_partition_map(name, &junk, 0, O_RDWR); 191 if (!map) { 192 fprintf(stderr, "pdisk: no valid partitions exist\n"); 193 return (CMD_FAIL); 194 } 195 part = atoi(argv[1]); 196 new_size = strtoul(argv[2], NULL, 10); 197 split_name = argv[3]; 198 split_type = argv[4]; 199 entry = find_entry_by_disk_address(part, map); 200 rv = CMD_FAIL; 201 if (!entry) { 202 fprintf(stderr, "pdisk: partition %d does not exist\n", part); 203 } 204 else if (strcmp(entry->data->dpme_type, kFreeType) == 0 205 || strcmp(entry->data->dpme_type, kMapType) == 0) { 206 fprintf(stderr, "pdisk: cannot split partition %d because its type is %s\n", 207 part, entry->data->dpme_type); 208 } 209 else if (!((new_size > 0) 210 && (new_size 211 <= (entry->data->dpme_pblocks - MIN_PARTITION_SIZE)) 212 && (new_size >= MIN_PARTITION_SIZE))) { 213 fprintf(stderr, "pdisk: split size of" 214 " partition %d must be between %u and %u\n", 215 part, (u32)MIN_PARTITION_SIZE, 216 (entry->data->dpme_pblocks - (u32)MIN_PARTITION_SIZE)); 217 } 218 else { 219 DPME save_dpme; 220 221 save_dpme = *entry->data; 222 delete_partition_from_map(entry); 223 add_partition_to_map(save_dpme.dpme_name, save_dpme.dpme_type, 224 save_dpme.dpme_pblock_start, new_size, map); 225 add_partition_to_map(split_name, split_type, 226 save_dpme.dpme_pblock_start + new_size, 227 save_dpme.dpme_pblocks - new_size, map); 228 write_partition_map(map); 229 230 entry = find_entry_by_base(save_dpme.dpme_pblock_start + new_size, map); 231 if (entry) { 232 printf("%lu\n", entry->disk_address); 233 } 234 rv = CMD_SUCCESS; 235 } 236 237 close_partition_map(map); 238 return (rv); 239} 240 241static int 242create_partition(char * name, int argc, char * * argv) 243{ 244 partition_map * entry; 245 int junk; 246 partition_map_header * map; 247 int rv = CMD_SUCCESS; 248 u32 part_base; 249 char * part_name; 250 u32 part_size; 251 char * part_type; 252 253 if (argc < 5) { 254 fprintf(stderr, "%s <name> <type> <base> <size>\n", 255 argv[0]); 256 return (CMD_FAIL); 257 } 258 map = open_partition_map(name, &junk, 0, O_RDWR); 259 if (!map) { 260 fprintf(stderr, "pdisk: disk is not partitioned\n"); 261 return (CMD_FAIL); 262 } 263 part_name = argv[1]; 264 part_type = argv[2]; 265 part_base = strtoul(argv[3], NULL, 10); 266 part_size = strtoul(argv[4], NULL, 10); 267 rv = CMD_FAIL; 268 if (add_partition_to_map(part_name, part_type, part_base, part_size, map) 269 == 1) { 270 write_partition_map(map); 271 entry = find_entry_by_base(part_base, map); 272 if (entry) { 273 printf("%lu\n", entry->disk_address); 274 rv = CMD_SUCCESS; 275 } 276 } 277 close_partition_map(map); 278 return (rv); 279} 280 281static int 282delete_partition(char * name, int argc, char * * argv) 283{ 284 partition_map * cur; 285 int junk; 286 partition_map_header * map; 287 int rv = CMD_SUCCESS; 288 u32 part_num; 289 290 if (argc < 2) { 291 fprintf(stderr, "%s <part>\n", 292 argv[0]); 293 return (CMD_FAIL); 294 } 295 map = open_partition_map(name, &junk, 0, O_RDWR); 296 if (!map) { 297 fprintf(stderr, "pdisk: disk is not partitioned\n"); 298 return (CMD_FAIL); 299 } 300 part_num = atoi(argv[1]); 301 rv = CMD_FAIL; 302 303 cur = find_entry_by_disk_address(part_num, map); 304 if (cur == NULL) { 305 fprintf(stderr, "No such partition\n"); 306 } else { 307 delete_partition_from_map(cur); 308 } 309 write_partition_map(map); 310 rv = CMD_SUCCESS; 311 312 close_partition_map(map); 313 return (rv); 314} 315 316void 317do_command_help() 318{ 319 cmdline_option_t * tbl_p; 320 321 fprintf(stderr, "command:\n"); 322 for (tbl_p = optionTable; tbl_p->name; tbl_p++) { 323 fprintf(stderr, "\t%-20s %s\n", tbl_p->name, tbl_p->description); 324 } 325} 326 327int 328do_command_line(int argc, char * argv[]) 329{ 330 char * devName = *argv; 331 cmdline_option_t * options_p; 332 333 argv++; 334 argc--; 335 if (!argc) { 336 return (CMD_FAIL); 337 } 338 for (options_p = &optionTable[0]; options_p->func; options_p++) { 339 if (strcmp(options_p->name, *argv) == 0) { 340 exit ((options_p->func)(devName, argc, argv)); 341 } 342 } 343 return (CMD_FAIL); 344} 345 346