int get_okay(const char *prompt, int default_value) { int c; flush_to_newline(0); printf("%s", prompt); for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == ' ' || c == '\t') { /* skip blanks and tabs */ } else if (c == '\n') { my_ungetch(c); return default_value; } else if (c == 'y' || c == 'Y') { return 1; } else if (c == 'n' || c == 'N') { return 0; } else { flush_to_newline(0); printf("%s", prompt); } } return -1; }
/* * Print a message on standard error & flush the input. */ void bad_input(const char *fmt,...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); flush_to_newline(1); }
partition_map_header * create_partition_map(char *name, partition_map_header *oldmap) { media *fd; partition_map_header * map; DPME *data; unsigned long number; int size; #ifdef __linux__ struct stat info; #endif fd = open_media(name, (rflag)?O_RDONLY:O_RDWR); if (fd == 0) { error(errno, "can't open file '%s' for %sing", name, (rflag)?"read":"writ"); return NULL; } map = (partition_map_header *) malloc(sizeof(partition_map_header)); if (map == NULL) { error(errno, "can't allocate memory for open partition map"); close_media(fd); return NULL; } map->fd = fd; map->name = name; map->writeable = (rflag)?0:1; map->changed = 1; map->disk_order = NULL; map->base_order = NULL; if (oldmap != NULL) { size = oldmap->physical_block; } else { size = fd->block_size; if (interactive) { printf("A physical block is %d bytes: ", size); flush_to_newline(0); get_number_argument("what should be the physical block size? ", (long *)&size, size); size = (size / PBLOCK_SIZE) * PBLOCK_SIZE; } } map->physical_block = size; // printf("block size is %d\n", map->physical_block); if (oldmap != NULL) { size = oldmap->logical_block; } else { size = PBLOCK_SIZE; if (interactive) { printf("A logical block is %d bytes: ", size); flush_to_newline(0); get_number_argument("what should be the logical block size? ", (long *)&size, size); size = (size / PBLOCK_SIZE) * PBLOCK_SIZE; } } map->logical_block = size; if (map->logical_block > MAXIOSIZE) { map->logical_block = MAXIOSIZE; } if (map->logical_block > map->physical_block) { map->physical_block = map->logical_block; } map->blocks_in_map = 0; map->maximum_in_map = -1; number = compute_device_size(map, oldmap); if (interactive) { printf("size of 'device' is %lu blocks (%d byte blocks): ", number, map->logical_block); flush_to_newline(0); get_number_argument("what should be the size? ", (long *)&number, number); if (number < 4) { number = 4; } printf("new size of 'device' is %lu blocks (%d byte blocks)\n", number, map->logical_block); } map->media_size = number; #ifdef __linux__ if (fstat(fd, &info) < 0) { error(errno, "can't stat file '%s'", name); map->regular_file = 0; } else { map->regular_file = S_ISREG(info.st_mode); } #else map->regular_file = 0; #endif map->misc = (Block0 *) malloc(PBLOCK_SIZE); if (map->misc == NULL) { error(errno, "can't allocate memory for block zero buffer"); } else { // got it! coerce_block0(map); sync_device_size(map); data = (DPME *) calloc(1, PBLOCK_SIZE); if (data == NULL) { error(errno, "can't allocate memory for disk buffers"); } else { // set data into entry data->dpme_signature = DPME_SIGNATURE; data->dpme_map_entries = 1; data->dpme_pblock_start = 1; data->dpme_pblocks = map->media_size - 1; strncpy(data->dpme_name, kFreeName, DPISTRLEN); strncpy(data->dpme_type, kFreeType, DPISTRLEN); data->dpme_lblock_start = 0; data->dpme_lblocks = data->dpme_pblocks; dpme_writable_set(data, 1); dpme_readable_set(data, 1); dpme_bootable_set(data, 0); dpme_in_use_set(data, 0); dpme_allocated_set(data, 0); dpme_valid_set(data, 1); if (add_data_to_map(data, 1, map) == 0) { free(data); } else { return map; } } } close_partition_map(map); return NULL; }
// // Routines // partition_map_header * open_partition_map(char *name, int *valid_file, int ask_logical_size) { media *fd; partition_map_header * map; int writeable; #ifdef __linux__ struct stat info; #endif int size; fd = open_media(name, (rflag)?O_RDONLY:O_RDWR); if (fd == 0) { fd = open_media(name, O_RDONLY); if (fd == 0) { error(errno, "can't open file '%s'", name); *valid_file = 0; return NULL; } else { writeable = 0; } } else { writeable = 1; } *valid_file = 1; map = (partition_map_header *) malloc(sizeof(partition_map_header)); if (map == NULL) { error(errno, "can't allocate memory for open partition map"); close_media(fd); return NULL; } map->fd = fd; map->name = name; map->writeable = (rflag)?0:writeable; map->changed = 0; map->disk_order = NULL; map->base_order = NULL; map->physical_block = fd->block_size; /* preflight */ map->misc = (Block0 *) malloc(PBLOCK_SIZE); if (map->misc == NULL) { error(errno, "can't allocate memory for block zero buffer"); close_media(map->fd); free(map); return NULL; } else if (read_media(map->fd, 0, (char *)map->misc, 0) == 0 || convert_block0(map->misc, 1) || coerce_block0(map)) { // if I can't read block 0 I might as well give up close_partition_map(map); return NULL; } map->physical_block = map->misc->sbBlkSize; // printf("physical block size is %d\n", map->physical_block); if (ask_logical_size && interactive) { size = PBLOCK_SIZE; printf("A logical block is %d bytes: ", size); flush_to_newline(0); get_number_argument("what should be the logical block size? ", (long *)&size, size); map->logical_block = (size / PBLOCK_SIZE) * PBLOCK_SIZE; } else { map->logical_block = PBLOCK_SIZE; } if (map->logical_block > MAXIOSIZE) { map->logical_block = MAXIOSIZE; } if (map->logical_block > map->physical_block) { map->physical_block = map->logical_block; } map->blocks_in_map = 0; map->maximum_in_map = -1; map->media_size = compute_device_size(map, map); sync_device_size(map); #ifdef __linux__ if (fstat(fd, &info) < 0) { error(errno, "can't stat file '%s'", name); map->regular_file = 0; } else { map->regular_file = S_ISREG(info.st_mode); } #else map->regular_file = 0; #endif if (read_partition_map(map) < 0) { // some sort of failure reading the map } else { // got it! ; return map; } close_partition_map(map); return NULL; }
int do_expert(partition_map_header *map, char *name) { int command; int quit = 0; while (get_command("Expert command (? for help): ", first_get, &command)) { first_get = 0; switch (command) { case '?': print_expert_notes(); // fall through case 'H': case 'h': printf("Commands are:\n"); printf(" h print help\n"); printf(" d dump block n\n"); printf(" p print the partition table\n"); if (dflag) { printf(" P (show data structures - debugging)\n"); } printf(" f full display of nth entry\n"); printf(" v validate map\n"); printf(" e examine patch partition\n"); printf(" q return to main edit menu\n"); printf(" Q quit editing\n"); break; case 'q': flush_to_newline(1); goto finis; break; case 'Q': if (map->changed) { if (get_okay("Discard changes? [n/y]: ", 0) != 1) { break; } } quit = 1; goto finis; break; case 'P': if (dflag) { show_data_structures(map); break; } // fall through case 'p': dump_partition_map(map, 1); break; case 'D': case 'd': do_display_block(map, name); break; case 'F': case 'f': do_display_entry(map); break; case 'V': case 'v': validate_map(map); break; case 'E': case 'e': do_examine_patch_partition(map); break; default: bad_input("No such command (%c)", command); break; } } finis: return quit; }
// // Edit the file // void edit(char *name, int ask_logical_size) { partition_map_header *map; int command; int order; int get_type; int valid_file; map = open_partition_map(name, &valid_file, ask_logical_size); if (!valid_file) { return; } printf("Edit %s -\n", name); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map != NULL && map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } #endif while (get_command("Command (? for help): ", first_get, &command)) { first_get = 0; order = 1; get_type = 0; switch (command) { case '?': print_edit_notes(); // fall through case 'H': case 'h': printf("Commands are:\n"); printf(" C (create with type also specified)\n"); printf(" c create new partition (standard unix root)\n"); printf(" d delete a partition\n"); printf(" h help\n"); printf(" i initialize partition map\n"); printf(" n (re)name a partition\n"); printf(" P (print ordered by base address)\n"); printf(" p print the partition table\n"); printf(" q quit editing\n"); printf(" r reorder partition entry in map\n"); printf(" s change size of partition map\n"); printf(" t change a partition's type\n"); if (!rflag) { printf(" w write the partition table\n"); } if (dflag) { printf(" x extra extensions for experts\n"); } break; case 'P': order = 0; // fall through case 'p': dump_partition_map(map, order); break; case 'Q': case 'q': if (map && map->changed) { if (get_okay("Discard changes? [n/y]: ", 0) != 1) { break; } } flush_to_newline(1); goto finis; break; case 'I': case 'i': map = init_partition_map(name, map); break; case 'C': get_type = 1; // fall through case 'c': do_create_partition(map, get_type); break; case 'N': case 'n': do_rename_partition(map); break; case 'D': case 'd': do_delete_partition(map); break; case 'R': case 'r': do_reorder(map); break; case 'S': case 's': do_change_map_size(map); break; case 'T': case 't': do_change_type(map); break; case 'X': case 'x': if (!dflag) { goto do_error; } else if (do_expert(map, name)) { flush_to_newline(1); goto finis; } break; case 'W': case 'w': if (!rflag) { do_write_partition_map(map); } else { goto do_error; } break; default: do_error: bad_input("No such command (%c)", command); break; } } finis: close_partition_map(map); }
partition_map_header * create_partition_map(char *name, partition_map_header *oldmap, int oflag) { MEDIA m; partition_map_header * map; DPME *data; unsigned long default_number; unsigned long number; long size; unsigned long multiple; m = open_pathname_as_media(name, oflag); if (m == 0) { error(errno, "can't open file '%s' for %sing", name, (oflag == O_RDONLY)?"read":"writ"); return NULL; } map = (partition_map_header *) malloc(sizeof(partition_map_header)); if (map == NULL) { error(errno, "can't allocate memory for open partition map"); close_media(m); return NULL; } map->name = name; map->writable = (oflag == O_RDONLY)?0:1; map->changed = 1; map->disk_order = NULL; map->base_order = NULL; if (oldmap != NULL) { size = oldmap->physical_block; } else { size = media_granularity(m); } m = open_deblock_media(PBLOCK_SIZE, m); map->m = m; if (interactive) { printf("A physical block is %ld bytes: ", size); flush_to_newline(0); get_number_argument("what should be the physical block size? ", &size, size); size = (size / PBLOCK_SIZE) * PBLOCK_SIZE; if (size < PBLOCK_SIZE) { size = PBLOCK_SIZE; } } if (map->physical_block > MAXIOSIZE) { map->physical_block = MAXIOSIZE; } map->physical_block = size; // printf("block size is %d\n", map->physical_block); if (oldmap != NULL) { size = oldmap->logical_block; } else { size = PBLOCK_SIZE; } if (interactive) { printf("A logical block is %ld bytes: ", size); flush_to_newline(0); get_number_argument("what should be the logical block size? ", &size, size); size = (size / PBLOCK_SIZE) * PBLOCK_SIZE; if (size < PBLOCK_SIZE) { size = PBLOCK_SIZE; } } #if 0 if (size > map->physical_block) { size = map->physical_block; } #endif map->logical_block = size; map->blocks_in_map = 0; map->maximum_in_map = -1; number = compute_device_size(map, oldmap); if (interactive) { printf("size of 'device' is %lu blocks (%d byte blocks): ", number, map->logical_block); default_number = number; flush_to_newline(0); do { if (get_number_argument("what should be the size? ", (long *)&number, default_number) == 0) { printf("Not a number\n"); flush_to_newline(1); number = 0; } else { multiple = get_multiplier(map->logical_block); if (multiple == 0) { printf("Bad multiplier\n"); number = 0; } else if (multiple != 1) { if (0xFFFFFFFF/multiple < number) { printf("Number too large\n"); number = 0; } else { number *= multiple; } } } default_number = kDefault; } while (number == 0); if (number < 4) { number = 4; } printf("new size of 'device' is %lu blocks (%d byte blocks)\n", number, map->logical_block); } map->media_size = number; map->misc = (Block0 *) calloc(1, PBLOCK_SIZE); if (map->misc == NULL) { error(errno, "can't allocate memory for block zero buffer"); } else { // got it! coerce_block0(map); sync_device_size(map); data = (DPME *) calloc(1, PBLOCK_SIZE); if (data == NULL) { error(errno, "can't allocate memory for disk buffers"); } else { // set data into entry data->dpme_signature = DPME_SIGNATURE; data->dpme_map_entries = 1; data->dpme_pblock_start = 1; data->dpme_pblocks = map->media_size - 1; strncpy(data->dpme_name, kFreeName, DPISTRLEN); strncpy(data->dpme_type, kFreeType, DPISTRLEN); data->dpme_lblock_start = 0; data->dpme_lblocks = data->dpme_pblocks; dpme_writable_set(data, 1); dpme_readable_set(data, 1); dpme_bootable_set(data, 0); dpme_in_use_set(data, 0); dpme_allocated_set(data, 0); dpme_valid_set(data, 1); if (add_data_to_map(data, 1, map) == 0) { free(data); } else { return map; } } } close_partition_map(map); return NULL; }
// // Routines // partition_map_header * open_partition_map(char *name, int *valid_file, int ask_logical_size, int oflag) { MEDIA m; partition_map_header * map; int writable; long size; m = open_pathname_as_media(name, oflag); if (m == 0) { m = open_pathname_as_media(name, O_RDONLY); if (m == 0) { error(errno, "can't open file '%s'", name); *valid_file = 0; return NULL; } else { writable = 0; } } else { writable = 1; } *valid_file = 1; map = (partition_map_header *) malloc(sizeof(partition_map_header)); if (map == NULL) { error(errno, "can't allocate memory for open partition map"); close_media(m); return NULL; } map->name = name; map->writable = (oflag == O_RDONLY)?0:writable; map->changed = 0; map->written = 0; map->disk_order = NULL; map->base_order = NULL; map->physical_block = media_granularity(m); /* preflight */ m = open_deblock_media(PBLOCK_SIZE, m); map->m = m; map->misc = (Block0 *) malloc(PBLOCK_SIZE); if (map->misc == NULL) { error(errno, "can't allocate memory for block zero buffer"); close_media(map->m); free(map); return NULL; } else if (read_media(map->m, (long long) 0, PBLOCK_SIZE, (char *)map->misc) == 0 || convert_block0(map->misc, 1) || coerce_block0(map)) { // if I can't read block 0 I might as well give up error(-1, "Can't read block 0 from '%s'", name); close_partition_map(map); return NULL; } map->physical_block = map->misc->sbBlkSize; //printf("physical block size is %d\n", map->physical_block); if (ask_logical_size && interactive) { size = PBLOCK_SIZE; printf("A logical block is %ld bytes: ", size); flush_to_newline(0); get_number_argument("what should be the logical block size? ", &size, size); size = (size / PBLOCK_SIZE) * PBLOCK_SIZE; if (size < PBLOCK_SIZE) { size = PBLOCK_SIZE; } map->logical_block = size; } else { map->logical_block = PBLOCK_SIZE; } if (map->logical_block > MAXIOSIZE) { map->logical_block = MAXIOSIZE; } if (map->logical_block > map->physical_block) { map->physical_block = map->logical_block; } map->blocks_in_map = 0; map->maximum_in_map = -1; map->media_size = compute_device_size(map, map); if (read_partition_map(map) < 0) { // some sort of failure reading the map } else { // got it! ; return map; } close_partition_map(map); return NULL; }