void combine_entry(partition_map *entry) { partition_map *p; u32 end; if (entry == NULL || istrncmp(entry->data->dpme_type, kFreeType, DPISTRLEN) != 0) { return; } if (entry->next_by_base != NULL) { p = entry->next_by_base; if (istrncmp(p->data->dpme_type, kFreeType, DPISTRLEN) != 0) { // next is not free } else if (entry->data->dpme_pblock_start + entry->data->dpme_pblocks != p->data->dpme_pblock_start) { // next is not contiguous (XXX this is bad) printf("next entry is not contiguous\n"); // start is already minimum // new end is maximum of two ends end = p->data->dpme_pblock_start + p->data->dpme_pblocks; if (end > entry->data->dpme_pblock_start + entry->data->dpme_pblocks) { entry->data->dpme_pblocks = end - entry->data->dpme_pblock_start; } entry->data->dpme_lblocks = entry->data->dpme_pblocks; delete_entry(p); } else { entry->data->dpme_pblocks += p->data->dpme_pblocks; entry->data->dpme_lblocks = entry->data->dpme_pblocks; delete_entry(p); } } if (entry->prev_by_base != NULL) { p = entry->prev_by_base; if (istrncmp(p->data->dpme_type, kFreeType, DPISTRLEN) != 0) { // previous is not free } else if (p->data->dpme_pblock_start + p->data->dpme_pblocks != entry->data->dpme_pblock_start) { // previous is not contiguous (XXX this is bad) printf("previous entry is not contiguous\n"); // new end is maximum of two ends end = p->data->dpme_pblock_start + p->data->dpme_pblocks; if (end < entry->data->dpme_pblock_start + entry->data->dpme_pblocks) { end = entry->data->dpme_pblock_start + entry->data->dpme_pblocks; } entry->data->dpme_pblocks = end - p->data->dpme_pblock_start; // new start is previous entry's start entry->data->dpme_pblock_start = p->data->dpme_pblock_start; entry->data->dpme_lblocks = entry->data->dpme_pblocks; delete_entry(p); } else { entry->data->dpme_pblock_start = p->data->dpme_pblock_start; entry->data->dpme_pblocks += p->data->dpme_pblocks; entry->data->dpme_lblocks = entry->data->dpme_pblocks; delete_entry(p); } } entry->contains_driver = contains_driver(entry); }
void resize_map(unsigned long new_size, partition_map_header *map) { partition_map * entry; partition_map * next; unsigned int incr; // find map entry entry = find_entry_by_type(kMapType, map); if (entry == NULL) { printf("Couldn't find entry for map!\n"); return; } next = entry->next_by_base; // same size if (new_size == entry->data->dpme_pblocks) { // do nothing return; } // make it smaller if (new_size < entry->data->dpme_pblocks) { if (next == NULL || istrncmp(next->data->dpme_type, kFreeType, DPISTRLEN) != 0) { incr = 1; } else { incr = 0; } if (new_size < map->blocks_in_map + incr) { printf("New size would be too small\n"); return; } goto doit; } // make it larger if (next == NULL || istrncmp(next->data->dpme_type, kFreeType, DPISTRLEN) != 0) { printf("No free space to expand into\n"); return; } if (entry->data->dpme_pblock_start + entry->data->dpme_pblocks != next->data->dpme_pblock_start) { printf("No contiguous free space to expand into\n"); return; } if (new_size > entry->data->dpme_pblocks + next->data->dpme_pblocks) { printf("No enough free space\n"); return; } doit: entry->data->dpme_type[0] = 0; delete_partition_from_map(entry); add_partition_to_map("Apple", kMapType, 1, new_size, map); map->maximum_in_map = new_size; }
int add_data_to_map(struct dpme *data, long ix, partition_map_header *map) { partition_map *entry; //printf("add data %d to map\n", ix); entry = (partition_map *) malloc(sizeof(partition_map)); if (entry == NULL) { error(errno, "can't allocate memory for map entries"); return 0; } entry->next_on_disk = NULL; entry->prev_on_disk = NULL; entry->next_by_base = NULL; entry->prev_by_base = NULL; entry->disk_address = ix; entry->the_map = map; entry->data = data; entry->contains_driver = contains_driver(entry); entry->HFS_name = get_HFS_name(entry, &entry->HFS_kind); insert_in_disk_order(entry); insert_in_base_order(entry); map->blocks_in_map++; if (map->maximum_in_map < 0) { if (istrncmp(data->dpme_type, kMapType, DPISTRLEN) == 0) { map->maximum_in_map = data->dpme_pblocks; } } return 1; }
partition_map * find_entry_by_type(const char *type_name, partition_map_header *map) { partition_map * cur; cur = map->base_order; while (cur != NULL) { if (istrncmp(cur->data->dpme_type, type_name, DPISTRLEN) == 0) { break; } cur = cur->next_by_base; } return cur; }
void dpme_init_flags(DPME *data) { if (istrncmp(data->dpme_type, kHFSType, DPISTRLEN) == 0) { /* XXX this is gross, fix it! */ data->dpme_flags = APPLE_HFS_FLAGS_VALUE; } else { 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, 1); dpme_valid_set(data, 1); } }
void delete_partition_from_map(partition_map *entry) { partition_map_header *map; DPME *data; if (istrncmp(entry->data->dpme_type, kMapType, DPISTRLEN) == 0) { printf("Can't delete entry for the map itself\n"); return; } if (entry->contains_driver) { printf("This program can't install drivers\n"); if (get_okay("are you sure you want to delete this driver? [n/y]: ", 0) != 1) { return; } } // if past end of disk, delete it completely if (entry->next_by_base == NULL && entry->data->dpme_pblock_start >= entry->the_map->media_size) { if (entry->contains_driver) { remove_driver(entry); // update block0 if necessary } delete_entry(entry); return; } // If at end of disk, incorporate extra disk space to partition if (entry->next_by_base == NULL) { entry->data->dpme_pblocks = entry->the_map->media_size - entry->data->dpme_pblock_start; } data = create_data(kFreeName, kFreeType, entry->data->dpme_pblock_start, entry->data->dpme_pblocks); if (data == NULL) { return; } if (entry->contains_driver) { remove_driver(entry); // update block0 if necessary } free(entry->data); free(entry->HFS_name); entry->HFS_kind = kHFS_not; entry->HFS_name = 0; entry->data = data; combine_entry(entry); map = entry->the_map; renumber_disk_addresses(map); map->changed = 1; }
void do_update_dpme(partition_map *entry) { int slice = 0; if (!entry) return; dpme_init_flags(entry->data); entry->HFS_name = get_HFS_name(entry, &entry->HFS_kind); if (istrncmp(entry->data->dpme_type, kUnixType, DPISTRLEN) == 0) { printf("Available partition slices for %s:\n",entry->data->dpme_type); printf(" a root partition\n"); printf(" b swap partition\n"); printf(" c do not set any bzb bits\n"); printf(" g user partition\n"); printf("Other lettered values will create user partitions\n"); get_command("Select a slice for default bzb values: ",0,&slice); } bzb_init_slice((BZB *)entry->data->dpme_bzb,slice); entry->the_map->changed = 1; }
int main() { char *str1 = istring_mk(NULL); char *str2 = istring_mk("Anders"); char *str3 = istring_mk("Alander"); char *str4 = istring_mk(" "); char *str9 = istring_to_string(str2); char *str5 = istrcat(str9,str4); char *str11 = istring_to_string(str5); char *str6 = istrcat(str11, str3); char *str7 = istring_to_string(str6); char *str8 = istring_mk("Erik"); char *str10 = istring_to_string(str5); char *str12 = "Anders Ålander"; char *str13 = istrncat(str9, str3,2); printf("An empty istring has length %zu\n", istrlen(str1)); printf("My first name is %s\n",str2); printf("My last name is %s\n",str3); printf("My name concatenated is %s\n", str6); printf("%s concatenated with the first %d chars from %s is %s\n", str2, 2, str3, str13); printf("%s has length %zu\n", str6, istrlen(str6)); printf("%s is my name stored as normal string, it also has length %zu\n", str7, strlen(str7)); printf("An istring's length can be changed without touching the string itself. %s has length %zu\n", str2, istrlen(str2)); str2 = istrslen(str2, 15); printf("but we can change it to %zu\n", istrlen(str2)); printf("Returns a pointer to the first given character in %s, for example a pointer to 's'gives %s\n", str2, istrchr(str2,'s')); printf("Same as above but from the end of %s. Pointer to 's' gives %s\n", str2, istrrchr(str2, 's')); printf("Are the strings %s and %s equal? %s\n", str2, str3, istrcmp(str2,str3)?"no":"yes"); printf("Which one of %s and %s is greatest? %s\n", str2, str3, istrcmp(str2,str3)<0?str2:str3); printf("Compares the first %d characters in %s and %s. The substring of %s is greatest\n", 3, str2, str3, istrncmp(str2, str3, 3) > 0?str3:str2); printf("The result of copying %s into %s is %s\n", str8, str12, istrcpy(str7, str8)); printf("The result of copying %d chars from %s into %s is %s\n", 3, str8, str12, istrncpy(str7,str8,3)); istring_rm(str1); istring_rm(str2); istring_rm(str3); istring_rm(str4); istring_rm(str5); istring_rm(str6); free(str7); istring_rm(str8); free(str9); free(str10); free(str11); istring_rm(str13); return 0; }
void do_create_partition(partition_map_header *map, int get_type) { long base; long length; char *name = 0; char *type_name = 0; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } // XXX add help feature (i.e. '?' in any argument routine prints help string) if (get_base_argument(&base, map) == 0) { return; } if (get_size_argument(&length, map) == 0) { return; } if (get_string_argument("Name of partition: ", &name, 1) == 0) { bad_input("Bad name"); return; } if (get_type == 0) { add_partition_to_map(name, kUnixType, base, length, map); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } goto xit1; #endif } else if (get_string_argument("Type of partition: ", &type_name, 1) == 0) { bad_input("Bad type"); goto xit1; } else { if (istrncmp(type_name, kFreeType, DPISTRLEN) == 0) { bad_input("Can't create a partition with the Free type"); goto xit2; } if (istrncmp(type_name, kMapType, DPISTRLEN) == 0) { bad_input("Can't create a partition with the Map type"); goto xit2; } add_partition_to_map(name, type_name, base, length, map); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } #endif } do_update_dpme(find_entry_by_base(base,map)); xit2: if (type_name) free(type_name); xit1: if (name) free(name); return; }
int add_partition_to_map(const char *name, const char *dptype, u32 base, u32 length, partition_map_header *map) { partition_map * cur; DPME *data; enum add_action act; int limit; u32 adjusted_base = 0; u32 adjusted_length = 0; u32 new_base = 0; u32 new_length = 0; // find a block that starts includes base and length cur = map->base_order; while (cur != NULL) { if (cur->data->dpme_pblock_start <= base && (base + length) <= (cur->data->dpme_pblock_start + cur->data->dpme_pblocks)) { break; } else { // check if request is past end of existing partitions, but on disk if ((cur->next_by_base == NULL) && (base + length <= map->media_size)) { // Expand final free partition if ((istrncmp(cur->data->dpme_type, kFreeType, DPISTRLEN) == 0) && base >= cur->data->dpme_pblock_start) { cur->data->dpme_pblocks = map->media_size - cur->data->dpme_pblock_start; break; } // create an extra free partition if (base >= cur->data->dpme_pblock_start + cur->data->dpme_pblocks) { if (map->maximum_in_map < 0) { limit = map->media_size; } else { limit = map->maximum_in_map; } if (map->blocks_in_map + 1 > limit) { printf("the map is not big enough\n"); return 0; } data = create_data(kFreeName, kFreeType, cur->data->dpme_pblock_start + cur->data->dpme_pblocks, map->media_size - (cur->data->dpme_pblock_start + cur->data->dpme_pblocks)); if (data != NULL) { if (add_data_to_map(data, cur->disk_address, map) == 0) { free(data); } } } } cur = cur->next_by_base; } } // if it is not Extra then punt if (cur == NULL || istrncmp(cur->data->dpme_type, kFreeType, DPISTRLEN) != 0) { printf("requested base and length is not " "within an existing free partition\n"); return 0; } // figure out what to do and sizes data = cur->data; if (data->dpme_pblock_start == base) { // replace or add if (data->dpme_pblocks == length) { act = kReplace; } else { act = kAdd; adjusted_base = base + length; adjusted_length = data->dpme_pblocks - length; } } else { // split or add if (data->dpme_pblock_start + data->dpme_pblocks == base + length) { act = kAdd; adjusted_base = data->dpme_pblock_start; adjusted_length = base - adjusted_base; } else { act = kSplit; new_base = data->dpme_pblock_start; new_length = base - new_base; adjusted_base = base + length; adjusted_length = data->dpme_pblocks - (length + new_length); } } // if the map will overflow then punt if (map->maximum_in_map < 0) { limit = map->media_size; } else { limit = map->maximum_in_map; } if (map->blocks_in_map + (int)act > limit) { printf("the map is not big enough\n"); return 0; } data = create_data(name, dptype, base, length); if (data == NULL) { return 0; } if (act == kReplace) { free(cur->data); cur->data = data; } else { // adjust this block's size cur->data->dpme_pblock_start = adjusted_base; cur->data->dpme_pblocks = adjusted_length; cur->data->dpme_lblocks = adjusted_length; // insert new with block address equal to this one if (add_data_to_map(data, cur->disk_address, map) == 0) { free(data); } else if (act == kSplit) { data = create_data(kFreeName, kFreeType, new_base, new_length); if (data != NULL) { // insert new with block address equal to this one if (add_data_to_map(data, cur->disk_address, map) == 0) { free(data); } } } } // renumber disk addresses renumber_disk_addresses(map); // mark changed map->changed = 1; return 1; }