static imgtoolerr_t datapack_read_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) { imgtool_image *image = imgtool_partition_image(partition); psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image); int index = seek_file_name(pack, filename); if (index >= 0) { if ((pack->pack_index[index].type & 0x7f) == 0x01) { // ODB files stream_seek(pack->stream, 0x10, SEEK_SET); get_odb(pack->stream, destf, pack->pack_index[index].type, pack->pack_index[index].id); } else if ((pack->pack_index[index].type & 0x7f) == 0x03) { // OB3/OPL files stream_seek(pack->stream, pack->pack_index[index].data_rec, SEEK_SET); get_ob3(pack->stream, destf, pack->pack_index[index].type, pack->pack_index[index].id); } else { // Other files return IMGTOOLERR_UNIMPLEMENTED; } return IMGTOOLERR_SUCCESS; } else return IMGTOOLERR_FILENOTFOUND; }
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_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) { imgtoolerr_t err; imgtool_image *img = imgtool_partition_image(partition); const os9_diskinfo *disk_info; struct os9_fileinfo file_info; UINT8 buffer[256]; int i, j; UINT32 file_size; UINT32 used_size; disk_info = os9_get_diskinfo(img); err = os9_lookup_path(img, filename, CREATE_NONE, &file_info, NULL, NULL, NULL); if (err) return err; if (file_info.directory) return IMGTOOLERR_FILENOTFOUND; file_size = file_info.file_size; for (i = 0; file_info.sector_map[i].count > 0; i++) { for (j = 0; j < file_info.sector_map[i].count; j++) { used_size = MIN(file_size, disk_info->sector_size); err = os9_read_lsn(img, file_info.sector_map[i].lsn + j, 0, buffer, used_size); if (err) return err; stream_write(destf, buffer, used_size); file_size -= used_size; } } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t os9_diskimage_writefile(imgtool_partition *partition, const char *path, const char *fork, imgtool_stream *sourcef, option_resolution *opts) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); struct os9_fileinfo file_info; size_t write_size; void *buf = NULL; int i = -1; UINT32 lsn = 0; UINT32 count = 0; UINT32 sz; const os9_diskinfo *disk_info; disk_info = os9_get_diskinfo(image); buf = malloc(disk_info->sector_size); if (!buf) { err = IMGTOOLERR_OUTOFMEMORY; goto done; } err = os9_lookup_path(image, path, CREATE_FILE, &file_info, NULL, NULL, NULL); if (err) goto done; sz = (UINT32) stream_size(sourcef); err = os9_set_file_size(image, &file_info, sz); if (err) goto done; while(sz > 0) { write_size = (size_t) MIN(sz, (UINT64) disk_info->sector_size); stream_read(sourcef, buf, write_size); while(count == 0) { i++; lsn = file_info.sector_map[i].lsn; count = file_info.sector_map[i].count; } err = os9_write_lsn(image, lsn, 0, buf, write_size); if (err) goto done; lsn++; count--; sz -= write_size; } done: if (buf) free(buf); return err; }
static imgtoolerr_t datapack_write_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, util::option_resolution *opts) { imgtool_image *image = imgtool_partition_image(partition); psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image); static const UINT8 data_head[4] = {0x02, 0x80, 0x00, 0x00}; UINT8 head[3]; UINT16 size = 0; UINT8 type = opts->lookup_int('T'); UINT8 file_id = opts->lookup_int('I'); if (!pack->eop) return IMGTOOLERR_CORRUPTIMAGE; // if not file_id is specified get the first free (for ODB only) if (file_id == 0 && type == 3) { file_id = get_free_file_id(pack); if (file_id == 0xff) return IMGTOOLERR_NOSPACE; } stream_read(sourcef, head, 3); stream_seek(pack->stream, pack->eop, SEEK_SET); if (type == 0) type = (!strncmp((char*)head, "ORG", 3)) ? 1 : 2; switch (type) { case 1: //OB3 file put_name_record(pack->stream, filename, 0x83, file_id); stream_write(pack->stream, data_head, 4); size = put_ob3(sourcef, pack->stream); break; case 2: //OPL file put_name_record(pack->stream, filename, 0x83, file_id); stream_write(pack->stream, data_head, 4); size = put_opl(sourcef, pack->stream); break; case 3: //ODB file put_name_record(pack->stream, filename, 0x81, file_id); size = put_odb(sourcef, pack->stream, file_id); break; } if (type != 3) { // update the OB3/OPL long record size stream_seek(pack->stream, pack->eop + 13, SEEK_SET); stream_putc(pack->stream, (size>>8) & 0xff); stream_putc(pack->stream, size & 0xff); }
static imgtoolerr_t os9_diskimage_freespace(imgtool_partition *partition, UINT64 *size) { imgtool_image *image = imgtool_partition_image(partition); const os9_diskinfo *disk_info; UINT32 free_lsns; disk_info = os9_get_diskinfo(image); free_lsns = os9_get_free_lsns(image); *size = free_lsns * disk_info->sector_size; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t rsdos_diskimage_deletefile(imgtool_partition *partition, const char *fname) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); int pos; struct rsdos_dirent ent; err = lookup_rsdos_file(image, fname, &ent, &pos); if (err) return err; return delete_entry(image, &ent, pos); }
static imgtoolerr_t datapack_free_space( imgtool_partition *partition, UINT64 *size) { imgtool_image *image = imgtool_partition_image( partition); psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image); UINT32 pack_size = 0; stream_seek(pack->stream, 0x07, SEEK_SET); stream_read(pack->stream, &pack_size, 1); if (size) *size = (pack_size * 0x2000) - pack->eop; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool_partition *partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length) { imgtoolerr_t ret; imgtool_image *image = imgtool_partition_image(partition); vzdos_dirent entry; if (fname) { ret = vzdos_get_dirent_fname(image, fname, &entry); if (ret) return ret; switch (entry.ftype) { case 'B': suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = filter_vzsnapshot_getinfo; suggestions[0].description = "VZ Snapshot"; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = NULL; suggestions[1].description = "Raw"; break; case 'T': suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = filter_vzsnapshot_getinfo; suggestions[0].description = "VZ Snapshot"; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = NULL; suggestions[1].description = "Raw"; suggestions[2].viability = SUGGESTION_POSSIBLE; suggestions[2].filter = filter_vzbas_getinfo; suggestions[2].description = "Tokenized Basic"; break; default: suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = NULL; suggestions[0].description = "Raw"; } } else { suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = NULL; suggestions[0].description = "Raw"; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = filter_vzsnapshot_getinfo; suggestions[1].description = "VZ Snapshot"; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t vzdos_diskimage_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) { imgtoolerr_t ret; imgtool_image *image = imgtool_partition_image(partition); int filesize, track, sector; vzdos_dirent ent; UINT8 buffer[DATA_SIZE + 2]; ret = vzdos_get_dirent_fname(image, filename, &ent); if (ret) return ret; filesize = ent.end_address - ent.start_address; track = ent.start_track; sector = ent.start_sector; while (filesize > 0) { int towrite; ret = vzdos_read_sector_data(image, track, sector, buffer); if (ret) return ret; /* detect sectors pointing to themselfs */ if ((track == pick_integer_le(buffer, DATA_SIZE, 1)) && (sector == pick_integer_le(buffer, DATA_SIZE + 1, 1))) return IMGTOOLERR_CORRUPTIMAGE; /* load next track and sector values */ track = pick_integer_le(buffer, DATA_SIZE, 1); sector = pick_integer_le(buffer, DATA_SIZE + 1, 1); /* track 0 is invalid */ if ((track == 0) && (filesize > DATA_SIZE)) return IMGTOOLERR_CORRUPTIMAGE; /* write either DATA_SIZE or the remaining bytes */ towrite = filesize > DATA_SIZE ? DATA_SIZE : filesize; if (stream_write(destf, buffer, towrite) != towrite) return IMGTOOLERR_WRITEERROR; filesize -= DATA_SIZE; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t vzsnapshot_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) { imgtoolerr_t ret; imgtool_image *image = imgtool_partition_image(partition); vzdos_dirent entry; UINT8 header[24]; /* get directory entry from disk */ ret = vzdos_get_dirent_fname(image, filename, &entry); if (ret) return ret; /* prepare header */ header[0] = 'V'; header[1] = 'Z'; header[2] = 'F'; switch (entry.ftype) { case 'B': header[3] = '1'; header[21] = 0xF1; break; case 'T': header[3] = '0'; header[21] = 0xF0; break; default: memset(header, 0x00, 4); header[21] = 0x00; } memset(header + 4, 0x00, 17); memcpy(header + 4, entry.fname, vzdos_get_fname_len(entry.fname) + 1); place_integer_le(header, 22, 2, entry.start_address); /* write header to file */ stream_write(destf, header, sizeof(header)); /* write data to file */ ret = vzdos_diskimage_readfile(partition, filename, "", destf); if (ret) return ret; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool_partition *partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); struct rsdos_dirent ent; int pos; if (fname) { err = lookup_rsdos_file(image, fname, &ent, &pos); if (err) return err; if (ent.asciiflag == (char) 0xFF) { /* ASCII file */ suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = filter_eoln_getinfo; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = NULL; } else if (ent.ftype == 0) { /* tokenized BASIC file */ suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = NULL; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = filter_cocobas_getinfo; } } else { suggestions[0].viability = SUGGESTION_RECOMMENDED; suggestions[0].filter = NULL; suggestions[1].viability = SUGGESTION_POSSIBLE; suggestions[1].filter = filter_eoln_getinfo; suggestions[2].viability = SUGGESTION_POSSIBLE; suggestions[2].filter = filter_cocobas_getinfo; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t rsdos_diskimage_readfile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *destf) { imgtoolerr_t err; struct rsdos_dirent ent; size_t size; imgtool_image *img = imgtool_partition_image(partition); err = lookup_rsdos_file(img, fname, &ent, NULL); if (err) return err; err = process_rsdos_file(&ent, img, destf, &size); if (err) return err; if (size == (size_t) -1) return IMGTOOLERR_CORRUPTIMAGE; return (imgtoolerr_t)0; }
static imgtoolerr_t rsdos_diskimage_freespace(imgtool_partition *partition, UINT64 *size) { floperr_t ferr; UINT8 i; size_t s = 0; UINT8 granule_count; UINT8 granule_map[MAX_GRANULEMAP_SIZE]; imgtool_image *image = imgtool_partition_image(partition); ferr = get_granule_map(image, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); for (i = 0; i < granule_count; i++) { if (granule_map[i] == 0xff) s += (9 * 256); } *size = s; return (imgtoolerr_t)FLOPPY_ERROR_SUCCESS; }
/* TRK 0 sector 15 is used to hold the track map of the disk with one bit corresponding to a sector used. */ static imgtoolerr_t vzdos_diskimage_freespace(imgtool_partition *partition, UINT64 *size) { imgtoolerr_t ret; int i; imgtool_image *image = imgtool_partition_image(partition); UINT8 c, v, buffer[DATA_SIZE + 2]; *size = 0; ret = vzdos_read_sector_data(image, 0, 15, buffer); if (ret) return ret; for (i = 0; i < DATA_SIZE; i++) { v = buffer[i]; for (c = 0; v; c++) { v &= v - 1; } *size += c * DATA_SIZE; } *size = (DATA_SIZE * 16 * 39) - *size; return IMGTOOLERR_SUCCESS; }
/* deletes directory entry, clears trackmap entries and sectors */ static imgtoolerr_t vzdos_diskimage_deletefile(imgtool_partition *partition, const char *fname) { imgtoolerr_t ret; imgtool_image *img = imgtool_partition_image(partition); int index, filesize, track, sector, next_track, next_sector; vzdos_dirent entry, next_entry; UINT8 buffer[DATA_SIZE + 2]; ret = vzdos_get_dirent_fname(img, fname, &entry); if (ret) return ret; ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, entry.start_track, sector_order[entry.start_sector], 24, &buffer, DATA_SIZE + 2); if (ret) return ret; filesize = entry.end_address - entry.start_address; track = entry.start_track; sector = entry.start_sector; /* delete directory entry */ ret = vzdos_searchentry(img, fname, &index); if (ret) return ret; ret = vzdos_get_dirent(img, index + 1, &next_entry); if (ret == IMGTOOLERR_FILENOTFOUND) { /* we are the last directory entry, just delete it */ ret = vzdos_clear_dirent(img, index); if (ret) return ret; } else if (ret) { /* an error occured */ return ret; } else { ret = vzdos_set_dirent(img, index++, next_entry); if (ret) return ret; while ((ret = vzdos_get_dirent(img, index + 1, &next_entry)) != IMGTOOLERR_FILENOTFOUND) { if (ret) return ret; ret = vzdos_set_dirent(img, index++, next_entry); if (ret) return ret; } ret = vzdos_clear_dirent(img, index); if (ret) return ret; } /* clear sectors and trackmap entries */ while (filesize > 0) { filesize -= DATA_SIZE; /* clear trackmap entry */ ret = vzdos_clear_trackmap(img, track, sector); if (ret) return ret; /* load next track and sector values */ next_track = pick_integer_le(buffer, DATA_SIZE, 1); next_sector = pick_integer_le(buffer, DATA_SIZE + 1, 1); /* overwrite sector with default values */ ret = vzdos_clear_sector(img, track, sector); if (ret) return ret; /* read next sector */ track = next_track; sector = next_sector; if (filesize > 0) { ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], 24, &buffer, DATA_SIZE + 2); if (ret) return ret; } } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t macbinary_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts) { 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; imgtool_image *image = imgtool_partition_image(partition); UINT8 header[128]; UINT32 datafork_size; UINT32 resourcefork_size; UINT64 total_size; UINT32 creation_time; UINT32 lastmodified_time; //int version; imgtool_attribute attr_values[10]; UINT32 type_code; UINT32 creator_code; UINT16 finder_flags; UINT16 coord_x; UINT16 coord_y; UINT16 finder_folder; UINT8 script_code = 0; UINT8 extended_flags = 0; /* read in the header */ memset(header, 0, sizeof(header)); stream_read(sourcef, header, sizeof(header)); /* check magic and zero fill bytes */ if (header[0] != 0x00) return IMGTOOLERR_CORRUPTFILE; if (header[74] != 0x00) return IMGTOOLERR_CORRUPTFILE; if (header[82] != 0x00) return IMGTOOLERR_CORRUPTFILE; datafork_size = pick_integer_be(header, 83, 4); resourcefork_size = pick_integer_be(header, 87, 4); total_size = stream_size(sourcef); /* size of a MacBinary header is always 128 bytes */ if (total_size - pad128(datafork_size) - pad128(resourcefork_size) != 128) return IMGTOOLERR_CORRUPTFILE; /* check filename length byte */ if ((header[1] <= 0x00) || (header[1] > 0x3F)) return IMGTOOLERR_CORRUPTFILE; /* check the CRC */ if (pick_integer_be(header, 124, 2) != ccitt_crc16(0, header, 124)) { /* the CRC does not match; this file is MacBinary I */ //version = 1; } else if (pick_integer_be(header, 102, 4) != 0x6D42494E) { /* did not see 'mBIN'; this file is MacBinary II */ if (header[122] < 0x81) return IMGTOOLERR_CORRUPTFILE; if (header[123] < 0x81) return IMGTOOLERR_CORRUPTFILE; //version = 2; } else { /* we did see 'mBIN'; this file is MacBinary III */ if (header[122] < 0x82) return IMGTOOLERR_CORRUPTFILE; if (header[123] < 0x81) return IMGTOOLERR_CORRUPTFILE; //version = 3; } type_code = pick_integer_be(header, 65, 4); creator_code = pick_integer_be(header, 69, 4); finder_flags = pick_integer_be(header, 73, 1) << 8; coord_x = pick_integer_be(header, 75, 2); coord_y = pick_integer_be(header, 77, 2); finder_folder = pick_integer_be(header, 79, 2); creation_time = pick_integer_be(header, 91, 4); lastmodified_time = pick_integer_be(header, 95, 4); if (image) { /* write out both forks */ err = write_fork(partition, filename, "", sourcef, sizeof(header), datafork_size, opts); if (err) return err; err = write_fork(partition, filename, "RESOURCE_FORK", sourcef, sizeof(header) + pad128(datafork_size), resourcefork_size, opts); if (err) return err; /* set up attributes */ attr_values[0].t = mac_crack_time(creation_time); attr_values[1].t = mac_crack_time(lastmodified_time); attr_values[2].i = type_code; attr_values[3].i = creator_code; attr_values[4].i = finder_flags; attr_values[5].i = coord_x; attr_values[6].i = coord_y; attr_values[7].i = finder_folder; attr_values[8].i = script_code; attr_values[9].i = extended_flags; err = imgtool_partition_put_file_attributes(partition, filename, attrs, attr_values); if (err) return err; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t os9_diskimage_delete(imgtool_partition *partition, const char *path, unsigned int delete_directory) { imgtoolerr_t err; imgtool_image *image = imgtool_partition_image(partition); //const os9_diskinfo *disk_info; struct os9_fileinfo file_info; UINT32 dirent_lsn, dirent_index; UINT32 entry_lsn, entry_index; UINT32 i, j, lsn; UINT8 b; //disk_info = os9_get_diskinfo(image); err = os9_lookup_path(image, path, CREATE_NONE, &file_info, NULL, &dirent_lsn, &dirent_index); if (err) return err; if (file_info.directory != delete_directory) return IMGTOOLERR_FILENOTFOUND; /* make sure that if we are deleting a directory, it is empty */ if (delete_directory) { for (i = 64; i < file_info.file_size; i += 32) { entry_index = i; entry_lsn = os9_lookup_lsn(image, &file_info, &entry_index); err = os9_read_lsn(image, entry_lsn, entry_index, &b, 1); if (err) return err; /* this had better be a deleted file, if not we can't delete */ if (b != 0) return IMGTOOLERR_DIRNOTEMPTY; } } /* zero out the file entry */ b = '\0'; err = os9_write_lsn(image, dirent_lsn, dirent_index, &b, 1); if (err) return err; /* get the link count */ err = os9_read_lsn(image, file_info.lsn, 8, &b, 1); if (err) return err; if (b > 0) b--; if (b > 0) { /* link count is greater than zero */ err = os9_write_lsn(image, file_info.lsn, 8, &b, 1); if (err) return err; } else { /* no more links; outright delete the file */ err = os9_deallocate_lsn(image, file_info.lsn); if (err) return err; for (i = 0; (i < ARRAY_LENGTH(file_info.sector_map)) && file_info.sector_map[i].count; i++) { lsn = file_info.sector_map[i].lsn; for (j = 0; j < file_info.sector_map[i].count; j++) { err = os9_deallocate_lsn(image, lsn + j); if (err) return err; } } } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t bml3_diskimage_writefile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions) { floperr_t ferr; imgtoolerr_t err; imgtool_image *img = imgtool_partition_image(partition); bml3_diskinfo *info = bml3_get_diskinfo(img); struct bml3_dirent ent, ent2; size_t i; UINT64 sz, read_sz; UINT64 freespace = 0; unsigned char g; unsigned char *gptr; UINT8 granule_count; UINT8 granule_map[MAX_GRANULEMAP_SIZE]; UINT8 eof_buf[MAX_SECTOR_SIZE]; // one-time setup of eof_buf memset(eof_buf, 0, sizeof(eof_buf)); eof_buf[0] = 0x1A; /* can we write to this image? */ if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; err = bml3_diskimage_freespace(partition, &freespace); if (err) return err; /* is there enough space? */ sz = read_sz = stream_size(sourcef); if (info->variant == 0) { // also need to write EOF sz++; } if (sz > freespace) return IMGTOOLERR_NOSPACE; /* setup our directory entry */ err = prepare_dirent(info->variant, &ent, fname); if (err) return err; ent.ftype = option_resolution_lookup_int(writeoptions, BML3_OPTIONS_FTYPE); ent.asciiflag = ((UINT8) option_resolution_lookup_int(writeoptions, BML3_OPTIONS_ASCII)) - 1; gptr = &ent.first_granule; ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); g = 0x00; do { while (granule_map[g] != 0xff) { g++; if ((g >= granule_count) || (g == 0)) return IMGTOOLERR_UNEXPECTED; /* We should have already verified that there is enough space */ } *gptr = g; gptr = &granule_map[g]; i = MIN(read_sz, info->granule_sectors * info->sector_size); if (i > 0) { err = transfer_to_granule(img, g, i, sourcef); if (err) return err; read_sz -= i; sz -= i; } if (i < info->granule_sectors * info->sector_size && sz > 0) { // write EOF and trailing NULs in the final sector ferr = write_granule(img, g, i, (info->granule_sectors * info->sector_size - i - 1) % info->sector_size + 1, eof_buf); if (ferr) return imgtool_floppy_error(ferr); sz--; i++; } /* Go to next granule */ g++; } while(sz > 0); /* Now that we are done with the file, we need to specify the final entry * in the file allocation table */ *gptr = 0xc0 + ((i + info->sector_size-1) / info->sector_size) - (info->variant == 0 ? 1 : 0); ent.lastsectorbytes = (i - 1) % info->sector_size + 1; /* delete file if it already exists */ err = bml3_diskimage_deletefile(partition, fname); if (err && err != IMGTOOLERR_FILENOTFOUND) return err; /* Now we need to find an empty directory entry */ i = -1; do { ferr = get_bml3_dirent(img, ++i, &ent2); if (ferr) return imgtool_floppy_error(ferr); } while(ent2.fname[0] != '\0' && ent2.fname[0] != -1); ferr = put_bml3_dirent(img, i, &ent); if (ferr) return imgtool_floppy_error(ferr); /* write the granule map back out */ ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t vzdos_writefile(imgtool_partition *partition, int offset, imgtool_stream *sourcef, vzdos_dirent *entry) { imgtoolerr_t ret; imgtool_image *img = imgtool_partition_image(partition); int index, track, sector, toread, next_track, next_sector; vzdos_dirent temp_entry; UINT64 filesize = 0, freespace = 0; UINT8 buffer[DATA_SIZE + 2]; char filename[9]; /* is the image writeable? */ if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; /* check for already existing filename -> overwrite */ strcpy(filename, entry->fname); filename[vzdos_get_fname_len(entry->fname) + 1] = 0x00; ret = vzdos_get_dirent_fname(img, filename, &temp_entry); if (!ret) { /* file already exists, delete it */ ret = vzdos_diskimage_deletefile(partition, filename); if (ret) return ret; } else if (ret != IMGTOOLERR_FILENOTFOUND) { /* another error occured, return it */ return ret; } ret = (imgtoolerr_t)stream_seek(sourcef, offset, SEEK_SET); if (ret) return ret; /* check if there is enough space */ filesize = stream_size(sourcef) - offset; ret = vzdos_diskimage_freespace(partition, &freespace); if (ret) return ret; if (filesize > freespace) return IMGTOOLERR_NOSPACE; /* get next free track and sector */ ret = vzdos_free_trackmap(img, &track, §or); if (ret) return ret; entry->end_address = entry->start_address + (unsigned int) filesize; entry->start_track = track; entry->start_sector = sector; /* search for next free directory entry */ for (index = 0; index < MAX_DIRENTS; index++) { ret = vzdos_get_dirent(img, index, &temp_entry); if (ret == IMGTOOLERR_FILENOTFOUND) break; else if (ret) return (ret); } /* write directory entry to disk */ ret = vzdos_set_dirent(img, index, *entry); if (ret) return ret; next_track = 0; next_sector = 0; /* write data to disk */ while (filesize > 0) { toread = filesize > DATA_SIZE ? DATA_SIZE : filesize; stream_read(sourcef, buffer, toread); filesize -= toread; /* mark sector as used */ ret = vzdos_set_trackmap(img, track, sector); if (ret) return ret; /* get track and sector for next sector */ if (filesize > 0) { ret = vzdos_free_trackmap(img, &next_track, &next_sector); if (ret) return ret; } else { next_track = 0; next_sector = 0; } buffer[DATA_SIZE] = next_track; buffer[DATA_SIZE + 1] = next_sector; /* write sector to disk */ ret = vzdos_write_sector_data(img, track, sector, buffer); if (ret) return ret; track = next_track; sector = next_sector; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t rsdos_diskimage_writefile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *sourcef, util::option_resolution *writeoptions) { floperr_t ferr; imgtoolerr_t err; imgtool_image *img = imgtool_partition_image(partition); struct rsdos_dirent ent, ent2; size_t i; UINT64 sz; UINT64 freespace = 0; unsigned char g; unsigned char *gptr; UINT8 granule_count; UINT8 granule_map[MAX_GRANULEMAP_SIZE]; /* can we write to this image? */ if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; err = rsdos_diskimage_freespace(partition, &freespace); if (err) return err; /* is there enough space? */ sz = stream_size(sourcef); if (sz > freespace) return IMGTOOLERR_NOSPACE; /* setup our directory entry */ err = prepare_dirent(&ent, fname); if (err) return err; ent.ftype = writeoptions->lookup_int(RSDOS_OPTIONS_FTYPE); ent.asciiflag = UINT8(writeoptions->lookup_int(RSDOS_OPTIONS_ASCII)) - 1; ent.lastsectorbytes_lsb = sz % 256; ent.lastsectorbytes_msb = (((sz % 256) == 0) && (sz > 0)) ? 1 : 0; gptr = &ent.first_granule; ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); g = 0x00; do { while (granule_map[g] != 0xff) { g++; if ((g >= granule_count) || (g == 0)) return IMGTOOLERR_UNEXPECTED; /* We should have already verified that there is enough space */ } *gptr = g; gptr = &granule_map[g]; i = std::min(sz, UINT64(9*256)); err = transfer_to_granule(img, g, i, sourcef); if (err) return err; sz -= i; /* Go to next granule */ g++; } while(sz > 0); /* Now that we are done with the file, we need to specify the final entry * in the file allocation table */ *gptr = 0xc0 + ((i + 255) / 256); /* Now we need to find an empty directory entry */ i = -1; do { ferr = get_rsdos_dirent(img, ++i, &ent2); if (ferr) return imgtool_floppy_error(ferr); } while((ent2.fname[0] != '\0') && strcmp(ent.fname, ent2.fname) && (ent2.fname[0] != -1)); /* delete file if it already exists */ if (ent2.fname[0] && (ent2.fname[0] != -1)) { err = delete_entry(img, &ent2, i); if (err) return err; } ferr = put_rsdos_dirent(img, i, &ent); if (ferr) return imgtool_floppy_error(ferr); /* write the granule map back out */ ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }