long close_deblock_media(MEDIA m) { DEBLOCK_MEDIA a; a = (DEBLOCK_MEDIA) m; if (a == 0) { return 0; } else if (a->m.kind != deblock_info.kind) { /* XXX need to error here - this is an internal problem */ return 0; } close_media(a->next_media); free(a->buffer); return 1; }
void close_partition_map(partition_map_header *map) { partition_map * entry; partition_map * next; if (map == NULL) { return; } free(map->misc); for (entry = map->disk_order; entry != NULL; entry = next) { next = entry->next_on_disk; free(entry->data); free(entry); } close_media(map->fd); free(map); }
void list_all_disks(void) { MEDIA_ITERATOR iter; MEDIA m; DPME * data; char *name; long mark; data = (DPME *) malloc(PBLOCK_SIZE); if (data == NULL) { error(errno, "can't allocate memory for try buffer"); return; } for (iter = first_media_kind(&mark); iter != 0; iter = next_media_kind(&mark)) { while ((name = step_media_iterator(iter)) != 0) { if ((m = open_pathname_as_media(name, O_RDONLY)) == 0) { #if defined(__linux__) || defined(__unix__) error(errno, "can't open file '%s'", name); #endif } else { close_media(m); dump(name); } free(name); } delete_media_iterator(iter); } free(data); }
void validate_map(partition_map_header *map) { range_list *list; char *name; unsigned int i; u32 limit; int printed; //printf("Validation not implemented yet.\n"); if (map == NULL) { the_map = 0; if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); return; } the_media = open_pathname_as_media(name, O_RDONLY); if (the_media == 0) { error(errno, "can't open file '%s'", name); free(name); return; } g = media_granularity(the_media); if (g < PBLOCK_SIZE) { g = PBLOCK_SIZE; } the_media = open_deblock_media(PBLOCK_SIZE, the_media); buffer = malloc(PBLOCK_SIZE); if (buffer == NULL) { error(errno, "can't allocate memory for disk buffer"); goto done; } } else { name = 0; the_map = map; g = map->logical_block; } initialize_list(&list); // get block 0 if (get_block_zero() == 0) { printf("unable to read block 0\n"); goto check_map; } // XXX signature valid // XXX size & count match DeviceCapacity // XXX number of descriptors matches array size // XXX each descriptor wholly contained in a partition // XXX the range below here is in physical blocks but the map is in logical blocks!!! add_range(&list, 1, b0->sbBlkCount-1, 0); /* subtract one since args are base & len */ check_map: // compute size of map if (map != NULL) { limit = the_map->blocks_in_map; } else { if (get_block_n(1) == 0) { printf("unable to get first block\n"); goto done; } else { if (mb->dpme_signature != DPME_SIGNATURE) { limit = -1; } else { limit = mb->dpme_map_entries; } } } // for each entry for (i = 1; ; i++) { #if 0 if (limit < 0) { /* XXX what to use for end of list? */ if (i > 5) { break; } } else #endif if (i > limit) { break; } printf("block %d:\n", i); // get entry if (get_block_n(i) == 0) { printf("\tunable to get\n"); goto post_processing; } printed = 0; // signature matches if (mb->dpme_signature != DPME_SIGNATURE) { printed = 1; printf("\tsignature is 0x%x, should be 0x%x\n", mb->dpme_signature, DPME_SIGNATURE); } // reserved1 == 0 if (mb->dpme_reserved_1 != 0) { printed = 1; printf("\treserved word is 0x%x, should be 0\n", mb->dpme_reserved_1); } // entry count matches #if 0 if (limit < 0) { printed = 1; printf("\tentry count is 0x%lx, real value unknown\n", mb->dpme_map_entries); } else #endif if (mb->dpme_map_entries != limit) { printed = 1; printf("\tentry count is 0x%lx, should be %ld\n", mb->dpme_map_entries, limit); } // lblocks contained within physical if (mb->dpme_lblock_start >= mb->dpme_pblocks || mb->dpme_lblocks > mb->dpme_pblocks - mb->dpme_lblock_start) { printed = 1; printf("\tlogical blocks (%ld for %ld) not within physical size (%ld)\n", mb->dpme_lblock_start, mb->dpme_lblocks, mb->dpme_pblocks); } // remember stuff for post processing add_range(&list, mb->dpme_pblock_start, mb->dpme_pblocks, 1); // XXX type is known type? // XXX no unknown flags? // XXX boot blocks either within or outside of logical // XXX checksum matches contents // XXX other fields zero if boot_bytes is zero // XXX processor id is known value? // XXX no data in reserved3 if (printed == 0) { printf("\tokay\n"); } } post_processing: // properties of whole map // every block on disk in one & only one partition coalesce_list(list); print_range_list(list); // there is a partition for the map // map fits within partition that contains it // try to detect 512/2048 mixed partition map? done: if (map == NULL) { close_media(the_media); free(buffer); free(name); } }
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; }
void write_partition_map(partition_map_header *map) { int fd; char *block; partition_map * entry; int i = 0; fd = map->fd->fd; if (map->misc != NULL) { convert_block0(map->misc, 0); write_block(map, 0, (char *)map->misc); convert_block0(map->misc, 1); } else { block = (char *) calloc(1, PBLOCK_SIZE); if (block != NULL) { write_block(map, 0, block); free(block); } } for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { convert_dpme(entry->data, 0); write_block(map, entry->disk_address, (char *)entry->data); convert_dpme(entry->data, 1); i = entry->disk_address; } #ifdef __linux__ // zap the block after the map (if possible) to get around a bug. if (map->maximum_in_map > 0 && i < map->maximum_in_map) { i += 1; block = (char *) malloc(PBLOCK_SIZE); if (block != NULL) { if (read_block(map, i, block, 1)) { block[0] = 0; write_block(map, i, block); } free(block); } } #endif /* __linux __ */ if (interactive) printf("The partition table has been altered!\n\n"); #ifdef __linux__ if (map->regular_file) { close_media(map->fd); } else { // printf("Calling ioctl() to re-read partition table.\n" // "(Reboot to ensure the partition table has been updated.)\n"); sync(); sleep(2); if ((i = ioctl(fd, BLKRRPART)) != 0) { saved_errno = errno; } else { // some kernel versions (1.2.x) seem to have trouble // rereading the partition table, but if asked to do it // twice, the second time works. - [email protected] */ sync(); sleep(2); if ((i = ioctl(fd, BLKRRPART)) != 0) { saved_errno = errno; } } close_media(map->fd); // printf("Syncing disks.\n"); sync(); sleep(4); /* for sync() */ if (i < 0) { error(saved_errno, "Re-read of partition table failed"); printf("Reboot your system to ensure the " "partition table is updated.\n"); } } #else close_media(map->fd); #endif map->fd = open_media(map->name, (map->writeable)?O_RDWR:O_RDONLY); if (map->fd == 0) { fatal(errno, "can't re-open file '%s' for %sing", map->name, (rflag)?"read":"writ"); } }
// // 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; }
void do_display_block(partition_map_header *map, char *alt_name) { MEDIA m; long number; char *name; static unsigned char *display_block; static int display_g; int g; static long next_number = -1; if (map != NULL) { name = 0; m = map->m; g = map->logical_block; } else { if (alt_name == 0) { if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); return; } } else { name = strdup(alt_name); } m = open_pathname_as_media(name, O_RDONLY); if (m == 0) { error(errno, "can't open file '%s'", name); free(name); return; } g = media_granularity(m); if (g < PBLOCK_SIZE) { g = PBLOCK_SIZE; } } if (get_number_argument("Block number: ", &number, next_number) == 0) { bad_input("Bad block number"); goto xit; } if (display_block == NULL || display_g < g) { if (display_block != NULL) { free(display_block); display_g = 0; } display_block = (unsigned char *) malloc(g); if (display_block == NULL) { error(errno, "can't allocate memory for display block buffer"); goto xit; } display_g = g; } if (read_media(m, ((long long)number) * g, g, (char *)display_block) != 0) { printf("block %ld -", number); dump_block((unsigned char*) display_block, g); next_number = number + 1; } xit: if (name) { close_media(m); free(name); } return; }
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; }