static imgtoolerr_t os9_diskimage_createdir(imgtool_partition *partition, const char *path) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); struct os9_fileinfo file_info; UINT8 dir_data[64]; UINT32 parent_lsn; err = os9_lookup_path(image, path, CREATE_DIR, &file_info, &parent_lsn, NULL, NULL); if (err) goto done; err = os9_set_file_size(image, &file_info, 64); if (err) goto done; /* create intial directories */ memset(dir_data, 0, sizeof(dir_data)); place_string(dir_data, 0, 32, ".."); place_integer_be(dir_data, 29, 3, parent_lsn); place_string(dir_data, 32, 32, "."); place_integer_be(dir_data, 61, 3, file_info.lsn); err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data)); if (err) goto done; done: return err; }
static imgtoolerr_t os9_diskimage_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts) { imgtoolerr_t err; dynamic_buffer header; UINT32 heads, tracks, sectors, sector_bytes, first_sector_id; UINT32 cluster_size, owner_id; UINT32 allocation_bitmap_bits, allocation_bitmap_lsns; UINT32 attributes, format_flags, disk_id; UINT32 i; INT32 total_allocated_sectors; const char *title; time_t t; struct tm *ltime; time(&t); ltime = localtime(&t); heads = option_resolution_lookup_int(opts, 'H'); tracks = option_resolution_lookup_int(opts, 'T'); sectors = option_resolution_lookup_int(opts, 'S'); sector_bytes = option_resolution_lookup_int(opts, 'L'); first_sector_id = option_resolution_lookup_int(opts, 'F'); title = ""; header.resize(sector_bytes); if (sector_bytes > 256) sector_bytes = 256; cluster_size = 1; owner_id = 1; disk_id = 1; attributes = 0; allocation_bitmap_bits = heads * tracks * sectors / cluster_size; allocation_bitmap_lsns = (allocation_bitmap_bits / 8 + sector_bytes - 1) / sector_bytes; format_flags = ((heads > 1) ? 0x01 : 0x00) | ((tracks > 40) ? 0x02 : 0x00); memset(&header[0], 0, sector_bytes); place_integer_be(&header[0], 0, 3, heads * tracks * sectors); place_integer_be(&header[0], 3, 1, sectors); place_integer_be(&header[0], 4, 2, (allocation_bitmap_bits + 7) / 8); place_integer_be(&header[0], 6, 2, cluster_size); place_integer_be(&header[0], 8, 3, 1 + allocation_bitmap_lsns); place_integer_be(&header[0], 11, 2, owner_id); place_integer_be(&header[0], 13, 1, attributes); place_integer_be(&header[0], 14, 2, disk_id); place_integer_be(&header[0], 16, 1, format_flags); place_integer_be(&header[0], 17, 2, sectors); place_string(&header[0], 31, 32, title); place_integer_be(&header[0], 103, 2, sector_bytes / 256); /* path descriptor options */ place_integer_be(&header[0], 0x3f+0x00, 1, 1); /* device class */ place_integer_be(&header[0], 0x3f+0x01, 1, 1); /* drive number */ place_integer_be(&header[0], 0x3f+0x03, 1, 0x20); /* device type */ place_integer_be(&header[0], 0x3f+0x04, 1, 1); /* density capability */ place_integer_be(&header[0], 0x3f+0x05, 2, tracks); /* number of tracks */ place_integer_be(&header[0], 0x3f+0x07, 1, heads); /* number of sides */ place_integer_be(&header[0], 0x3f+0x09, 2, sectors); /* sectors per track */ place_integer_be(&header[0], 0x3f+0x0b, 2, sectors); /* sectors on track zero */ place_integer_be(&header[0], 0x3f+0x0d, 1, 3); /* sector interleave factor */ place_integer_be(&header[0], 0x3f+0x0e, 1, 8); /* default sectors per allocation */ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 7; for (i = 0; i < allocation_bitmap_lsns; i++) { memset(&header[0], 0x00, sector_bytes); if (total_allocated_sectors > (8 * 256)) { memset(&header[0], 0xff, sector_bytes); total_allocated_sectors -= (8 * 256); } else if (total_allocated_sectors > 1 ) { int offset; UINT8 mask; while( total_allocated_sectors >= 0 ) { offset = total_allocated_sectors / 8; mask = 1 << (7 - ( total_allocated_sectors % 8 ) ); header[offset] |= mask; total_allocated_sectors--; } } err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + i, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } memset(&header[0], 0, sector_bytes); header[0x00] = 0xBF; header[0x01] = 0x00; header[0x02] = 0x00; header[0x03] = (UINT8) ltime->tm_year; header[0x04] = (UINT8) ltime->tm_mon + 1; header[0x05] = (UINT8) ltime->tm_mday; header[0x06] = (UINT8) ltime->tm_hour; header[0x07] = (UINT8) ltime->tm_min; header[0x08] = 0x02; header[0x09] = 0x00; header[0x0A] = 0x00; header[0x0B] = 0x00; header[0x0C] = 0x40; header[0x0D] = (UINT8) (ltime->tm_year % 100); header[0x0E] = (UINT8) ltime->tm_mon; header[0x0F] = (UINT8) ltime->tm_mday; place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1); place_integer_be(&header[0], 0x13, 2, 8); err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; memset(&header[0], 0, sector_bytes); header[0x00] = 0x2E; header[0x01] = 0xAE; header[0x1F] = 1 + allocation_bitmap_lsns; header[0x20] = 0xAE; header[0x3F] = 1 + allocation_bitmap_lsns; err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 2 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TOOD: pass ddam argument from imgtool */ if (err) goto done; done: return err; }
static imgtoolerr_t os9_lookup_path(imgtool_image *img, const char *path, creation_policy_t create, struct os9_fileinfo *file_info, UINT32 *parent_lsn, UINT32 *dirent_lsn, UINT32 *dirent_index) { imgtoolerr_t err = IMGTOOLERR_SUCCESS; struct os9_fileinfo dir_info; UINT32 index, current_lsn, dir_size; UINT32 entry_index = 0; UINT32 free_entry_index = 0xffffffff; UINT32 entry_lsn = 0; UINT32 allocated_lsn = 0; UINT8 entry[32]; UINT8 block[64]; char *filename; const os9_diskinfo *disk_info; disk_info = os9_get_diskinfo(img); current_lsn = disk_info->root_dir_lsn; if (parent_lsn) *parent_lsn = 0; /* we have to transverse each path element */ while(*path) { if (parent_lsn) *parent_lsn = current_lsn; /* decode the directory header of this directory */ err = os9_decode_file_header(img, current_lsn, &dir_info); if (err) goto done; dir_size = dir_info.file_size; /* sanity check directory */ if (!dir_info.directory) { err = (current_lsn == disk_info->root_dir_lsn) ? IMGTOOLERR_CORRUPTIMAGE : IMGTOOLERR_INVALIDPATH; goto done; } /* walk the directory */ for (index = 0; index < dir_size; index += 32) { entry_index = index; entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); err = os9_read_lsn(img, entry_lsn, entry_index, entry, sizeof(entry)); if (err) goto done; /* remember first free entry found */ if( free_entry_index == 0xffffffff ) { if( entry[0] == 0 ) free_entry_index = index; } if (os9_interpret_dirent(entry, &filename, ¤t_lsn, NULL)) { if (!strcmp(path, filename)) break; } } /* at the end of the file? */ if (index >= dir_size) { /* if we're not creating, or we are creating but we have not fully * transversed the directory, error out */ if (!create || path[strlen(path) + 1]) { err = IMGTOOLERR_PATHNOTFOUND; goto done; } /* allocate a new LSN */ err = os9_allocate_lsn(img, &allocated_lsn); if (err) goto done; /* write the file */ memset(block, 0, sizeof(block)); place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00)); err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block)); if (err) goto done; if( free_entry_index == 0xffffffff ) { /* expand the directory to hold the new entry */ err = os9_set_file_size(img, &dir_info, dir_size + 32); if (err) goto done; } else /* use first unused entry in directory */ dir_size = free_entry_index; /* now prepare the directory entry */ memset(entry, 0, sizeof(entry)); place_string(entry, 0, 28, path); place_integer_be(entry, 29, 3, allocated_lsn); /* now write the directory entry */ entry_index = dir_size; entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); err = os9_write_lsn(img, entry_lsn, entry_index, entry, 32); if (err) goto done; /* directory entry append complete; no need to hold this lsn */ current_lsn = allocated_lsn; allocated_lsn = 0; } path += strlen(path) + 1; } if (file_info) { err = os9_decode_file_header(img, current_lsn, file_info); if (err) goto done; } if (dirent_lsn) *dirent_lsn = entry_lsn; if (dirent_index) *dirent_index = entry_index; done: if (allocated_lsn != 0) os9_deallocate_lsn(img, allocated_lsn); return err; }
static imgtoolerr_t os9_set_file_size(imgtool_image *image, struct os9_fileinfo *file_info, UINT32 new_size) { imgtoolerr_t err; const os9_diskinfo *disk_info; UINT32 new_lsn_count, current_lsn_count; UINT32 free_lsns, lsn, i; int sector_map_length = -1; UINT8 header[256]; /* easy way out? */ if (file_info->file_size == new_size) return IMGTOOLERR_SUCCESS; disk_info = os9_get_diskinfo(image); free_lsns = os9_get_free_lsns(image); current_lsn_count = (file_info->file_size + disk_info->sector_size - 1) / disk_info->sector_size; new_lsn_count = (new_size + disk_info->sector_size - 1) / disk_info->sector_size; /* check to see if the file is growing and we do not have enough space */ if ((new_lsn_count > current_lsn_count) && (new_lsn_count - current_lsn_count > free_lsns)) return IMGTOOLERR_NOSPACE; if (current_lsn_count != new_lsn_count) { /* first find out the size of our sector map */ sector_map_length = 0; lsn = 0; while((lsn < current_lsn_count) && (sector_map_length < ARRAY_LENGTH(file_info->sector_map))) { if (file_info->sector_map[sector_map_length].count == 0) return os9_corrupt_file_error(file_info); lsn += file_info->sector_map[sector_map_length].count; sector_map_length++; } /* keep in mind that the sector_map might not parallel our expected * current LSN count; we should tolerate this abnormality */ current_lsn_count = lsn; while(current_lsn_count > new_lsn_count) { /* shrink this file */ lsn = file_info->sector_map[sector_map_length - 1].lsn + file_info->sector_map[sector_map_length - 1].count - 1; err = os9_deallocate_lsn(image, lsn); if (err) return err; file_info->sector_map[sector_map_length - 1].count--; while(sector_map_length > 0 && (file_info->sector_map[sector_map_length - 1].count == 0)) sector_map_length--; current_lsn_count--; } while(current_lsn_count < new_lsn_count) { /* grow this file */ err = os9_allocate_lsn(image, &lsn); if (err) return err; if ((sector_map_length > 0) && ((file_info->sector_map[sector_map_length - 1].lsn + file_info->sector_map[sector_map_length - 1].count) == lsn)) { file_info->sector_map[sector_map_length - 1].count++; } else if (sector_map_length >= ARRAY_LENGTH(file_info->sector_map)) { return IMGTOOLERR_NOSPACE; } else { file_info->sector_map[sector_map_length].lsn = lsn; file_info->sector_map[sector_map_length].count = 1; sector_map_length++; file_info->sector_map[sector_map_length].lsn = 0; file_info->sector_map[sector_map_length].count = 0; } current_lsn_count++; } } /* now lets write back the sector */ err = os9_read_lsn(image, file_info->lsn, 0, header, sizeof(header)); if (err) return err; file_info->file_size = new_size; place_integer_be(header, 9, 4, file_info->file_size); /* do we have to write the sector map? */ if (sector_map_length >= 0) { for (i = 0; i < MIN(sector_map_length + 1, ARRAY_LENGTH(file_info->sector_map)); i++) { place_integer_be(header, 16 + (i * 5) + 0, 3, file_info->sector_map[i].lsn); place_integer_be(header, 16 + (i * 5) + 3, 2, file_info->sector_map[i].count); } } err = os9_write_lsn(image, file_info->lsn, 0, header, disk_info->sector_size); if (err) return err; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t macbinary_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) { static const UINT32 attrs[] = { IMGTOOLATTR_TIME_CREATED, IMGTOOLATTR_TIME_LASTMODIFIED, IMGTOOLATTR_INT_MAC_TYPE, IMGTOOLATTR_INT_MAC_CREATOR, IMGTOOLATTR_INT_MAC_FINDERFLAGS, IMGTOOLATTR_INT_MAC_COORDX, IMGTOOLATTR_INT_MAC_COORDY, IMGTOOLATTR_INT_MAC_FINDERFOLDER, IMGTOOLATTR_INT_MAC_SCRIPTCODE, IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS, 0 }; imgtoolerr_t err; UINT8 header[128]; const char *basename; int i; UINT32 type_code = 0x3F3F3F3F; UINT32 creator_code = 0x3F3F3F3F; UINT16 finder_flags = 0; UINT16 coord_x = 0; UINT16 coord_y = 0; UINT16 finder_folder = 0; UINT8 script_code = 0; UINT8 extended_flags = 0; imgtool_forkent fork_entries[4]; const imgtool_forkent *data_fork = NULL; const imgtool_forkent *resource_fork = NULL; UINT32 creation_time = 0; UINT32 lastmodified_time = 0; imgtool_attribute attr_values[10]; /* get the forks */ err = imgtool_partition_list_file_forks(partition, filename, fork_entries, sizeof(fork_entries)); if (err) return err; for (i = 0; fork_entries[i].type != FORK_END; i++) { if (fork_entries[i].type == FORK_DATA) data_fork = &fork_entries[i]; else if (fork_entries[i].type == FORK_RESOURCE) resource_fork = &fork_entries[i]; } /* get the attributes */ err = imgtool_partition_get_file_attributes(partition, filename, attrs, attr_values); if (err && (ERRORCODE(err) != IMGTOOLERR_UNIMPLEMENTED)) return err; if (err == IMGTOOLERR_SUCCESS) { creation_time = mac_setup_time(attr_values[0].t); lastmodified_time = mac_setup_time(attr_values[1].t); type_code = attr_values[2].i; creator_code = attr_values[3].i; finder_flags = attr_values[4].i; coord_x = attr_values[5].i; coord_y = attr_values[6].i; finder_folder = attr_values[7].i; script_code = attr_values[8].i; extended_flags = attr_values[9].i; } memset(header, 0, sizeof(header)); /* place filename */ basename = filename; while(basename[strlen(basename) + 1]) basename += strlen(basename) + 1; pascal_from_c_string((unsigned char *) &header[1], 64, basename); place_integer_be(header, 65, 4, type_code); place_integer_be(header, 69, 4, creator_code); place_integer_be(header, 73, 1, (finder_flags >> 8) & 0xFF); place_integer_be(header, 75, 2, coord_x); place_integer_be(header, 77, 2, coord_y); place_integer_be(header, 79, 2, finder_folder); place_integer_be(header, 83, 4, data_fork ? data_fork->size : 0); place_integer_be(header, 87, 4, resource_fork ? resource_fork->size : 0); place_integer_be(header, 91, 4, creation_time); place_integer_be(header, 95, 4, lastmodified_time); place_integer_be(header, 101, 1, (finder_flags >> 0) & 0xFF); place_integer_be(header, 102, 4, 0x6D42494E); place_integer_be(header, 106, 1, script_code); place_integer_be(header, 107, 1, extended_flags); place_integer_be(header, 122, 1, 0x82); place_integer_be(header, 123, 1, 0x81); place_integer_be(header, 124, 2, ccitt_crc16(0, header, 124)); stream_write(destf, header, sizeof(header)); if (data_fork) { err = imgtool_partition_read_file(partition, filename, "", destf, NULL); if (err) return err; stream_fill(destf, 0, pad128(data_fork->size)); } if (resource_fork) { err = imgtool_partition_read_file(partition, filename, "RESOURCE_FORK", destf, NULL); if (err) return err; stream_fill(destf, 0, pad128(resource_fork->size)); } return IMGTOOLERR_SUCCESS; }