static imgtoolerr_t delete_entry(imgtool::image &img, rsdos_dirent &ent, int pos) { floperr_t ferr; unsigned char g, i; uint8_t granule_count; uint8_t granule_map[MAX_GRANULEMAP_SIZE]; // write a NUL in the filename, marking it deleted ent.filename[0] = 0; ferr = put_rsdos_dirent(img, pos, ent); if (ferr) return imgtool_floppy_error(ferr); ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); // now free up the granules g = ent.first_granule; while (g < granule_count) { i = granule_map[g]; granule_map[g] = 0xff; g = i; } ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t delete_entry(imgtool_image *img, struct rsdos_dirent *ent, int pos) { floperr_t ferr; unsigned char g, i; UINT8 granule_count; UINT8 granule_map[MAX_GRANULEMAP_SIZE]; /* Write a NUL in the filename, marking it deleted */ ent->fname[0] = 0; ferr = put_rsdos_dirent(img, pos, ent); if (ferr) return imgtool_floppy_error(ferr); ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); /* Now free up the granules */ g = ent->first_granule; while (g < granule_count) { i = granule_map[g]; granule_map[g] = 0xff; g = i; } ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_open_internal(imgtool_image *image, imgtool_stream *f, int noclose) { floperr_t ferr; imgtoolerr_t err; struct imgtool_floppy_image *fimg; const struct ImgtoolFloppyExtra *extra; extra = get_extra(img_module(image)); fimg = (struct imgtool_floppy_image *) img_extrabytes(image); /* open up the floppy */ ferr = floppy_open(f, noclose ? &imgtool_noclose_ioprocs : &imgtool_ioprocs, NULL, extra->format, FLOPPY_FLAGS_READWRITE, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); return err; } if (extra->open) { err = extra->open(image, NULL); if (err) return err; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t lookup_rsdos_file(imgtool_image *f, const char *fname, struct rsdos_dirent *ent, int *position) { int i; floperr_t ferr; char fnamebuf[13]; i = 0; fnamebuf[0] = '\0'; do { do { ferr = get_rsdos_dirent(f, i++, ent); if (ferr) return imgtool_floppy_error(ferr); } while(ent->fname[0] == '\0'); if (ent->fname[0] != -1) get_dirent_fname(fnamebuf, ent); } while((ent->fname[0] != -1) && core_stricmp(fnamebuf, fname)); if (ent->fname[0] == -1) return IMGTOOLERR_FILENOTFOUND; if (position) *position = i - 1; return (imgtoolerr_t)0; }
static imgtoolerr_t imgtool_floppy_transfer_sector_tofrom_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f, int direction) { floperr_t err; floppy_image_legacy *floppy; dynamic_buffer buffer; floppy = imgtool_floppy(img); buffer.resize(length); if (direction) { err = floppy_read_sector(floppy, head, track, sector, offset, buffer, length); if (err) goto done; stream_write(f, buffer, length); } else { stream_read(f, buffer, length); err = floppy_write_sector(floppy, head, track, sector, offset, buffer, length, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } err = FLOPPY_ERROR_SUCCESS; done: return imgtool_floppy_error(err); }
static imgtoolerr_t imgtool_floppy_open_internal(imgtool_image *image, imgtool_stream *f, int noclose) { floperr_t ferr; imgtoolerr_t err; struct imgtool_floppy_image *fimg; const imgtool_class *imgclass; const struct FloppyFormat *format; imgtoolerr_t (*open)(imgtool_image *image, imgtool_stream *f); fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(image); imgclass = &imgtool_image_module(image)->imgclass; format = (const struct FloppyFormat *) imgclass->derived_param; open = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN); /* open up the floppy */ ferr = floppy_open(f, noclose ? &imgtool_noclose_ioprocs : &imgtool_ioprocs, NULL, format, FLOPPY_FLAGS_READWRITE, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); return err; } if (open) { err = open(image, NULL); if (err) return err; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, rsdos_dirent &ent, int *position = nullptr) { int i; floperr_t ferr; std::string fnamebuf; i = 0; do { do { ferr = get_rsdos_dirent(f, i++, ent); if (ferr) return imgtool_floppy_error(ferr); } while(ent.filename[0] == '\0'); if (ent.filename[0] != -1) fnamebuf = get_dirent_fname(ent); } while((ent.filename[0] != -1) && core_stricmp(fnamebuf.c_str(), fname)); if (ent.filename[0] == -1) return IMGTOOLERR_FILENOTFOUND; if (position) *position = i - 1; return (imgtoolerr_t)0; }
static imgtoolerr_t rsdos_diskimage_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent) { floperr_t ferr; imgtoolerr_t err; size_t filesize; rsdos_direnum *rsenum; rsdos_dirent rsent; imgtool::image &image(enumeration.image()); rsenum = (rsdos_direnum *) enumeration.extra_bytes(); /* Did we hit the end of file before? */ if (rsenum->eof) goto eof; do { if (rsenum->index >= MAX_DIRENTS) goto eof; ferr = get_rsdos_dirent(image, rsenum->index++, rsent); if (ferr) return imgtool_floppy_error(ferr); } while(rsent.filename[0] == '\0'); // now are we at the eof point? if (rsent.filename[0] == -1) { rsenum->eof = 1; eof: ent.eof = 1; } else { /* Not the end of file */ err = process_rsdos_file(&rsent, image, nullptr, filesize); if (err) return err; if (filesize == ((size_t) -1)) { /* corrupt! */ ent.filesize = 0; ent.corrupt = 1; } else { ent.filesize = filesize; ent.corrupt = 0; } ent.eof = 0; std::string fname = get_dirent_fname(rsent); snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fname.c_str()); snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B')); } return IMGTOOLERR_SUCCESS; }
imgtoolerr_t imgtool_floppy_read_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len) { floperr_t ferr; ferr = floppy_read_sector(get_floppy(image), head, track, sector, 0, buffer, len); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_get_sector_size(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size) { floperr_t ferr; ferr = floppy_get_sector_length(imgtool_floppy(image), head, track, sector, sector_size); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_write_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam) { floperr_t ferr; ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, len, ddam); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t get_file_size(struct bml3_dirent *ent, imgtool_image *img, const struct granule_list_t *granule_list, size_t *size) { floperr_t ferr; size_t last_sector_bytes = 0; bml3_diskinfo *info = bml3_get_diskinfo(img); // TODO are these special cases valid, or maybe indicate a corrupt image? if (granule_list->granule_count == 0) { *size = 0; return IMGTOOLERR_SUCCESS; } else if (granule_list->last_granule_sectors == 0) { *size = info->sector_size * ((granule_list->granule_count - 1) * info->granule_sectors); return IMGTOOLERR_SUCCESS; } // determine size excluding final sector *size = info->sector_size * ((granule_list->granule_count - 1) * info->granule_sectors + granule_list->last_granule_sectors - 1); // determine bytes used in final sector switch (info->variant) { case 0: // look for EOF (ASCII SUB) and trailing NULs in final sector { UINT8 buf[MAX_SECTOR_SIZE]; ferr = read_granule(img, granule_list->granules[granule_list->granule_count-1], info->sector_size * (granule_list->last_granule_sectors - 1), info->sector_size, buf); if (ferr) return imgtool_floppy_error(ferr); for (last_sector_bytes = info->sector_size - 1; ; last_sector_bytes--) { if (buf[last_sector_bytes] != 0) break; if (last_sector_bytes == 0) break; } if (buf[last_sector_bytes] != 0x1a) { last_sector_bytes++; } } break; case 1: last_sector_bytes = ent->lastsectorbytes; break; } // TODO is it valid for last_sector_bytes == 0? if (last_sector_bytes > info->sector_size) { return IMGTOOLERR_CORRUPTIMAGE; } *size += last_sector_bytes; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t os9_write_lsn(imgtool_image *img, UINT32 lsn, int offset, const void *buffer, size_t buffer_len) { imgtoolerr_t err; floperr_t ferr; UINT32 head, track, sector; err = os9_locate_lsn(img, lsn, &head, &track, §or); if (err) return err; ferr = floppy_write_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len, 0); /* TODO: pass ddam argument from imgtool */ if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t os9_read_lsn(imgtool_image *img, UINT32 lsn, int offset, void *buffer, size_t buffer_len) { imgtoolerr_t err; floperr_t ferr; UINT32 head, track, sector; err = os9_locate_lsn(img, lsn, &head, &track, §or); if (err) return err; ferr = floppy_read_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t bml3_diskimage_open(imgtool_image *image, imgtool_stream *stream) { // imgtoolerr_t err; floperr_t ferr; bml3_diskinfo *info = bml3_get_diskinfo(image); floppy_image_legacy *floppy = imgtool_floppy(image); const struct FloppyCallbacks *callbacks = floppy_callbacks(floppy); // probe disk geometry to guess format int heads_per_disk = callbacks->get_heads_per_disk(floppy); UINT32 sector_length; ferr = callbacks->get_sector_length(floppy, 0, 20, 1, §or_length); if (ferr) return imgtool_floppy_error(ferr); int sectors_per_track = callbacks->get_sectors_per_track(floppy, 0, 20); if (heads_per_disk == 2 && sector_length == 128 && sectors_per_track == 16) { // single-sided, single-density info->sector_size = 128; info->heads = 1; info->fat_start_sector = 1; info->fat_start_offset = 5; info->fat_sectors = 2; info->dirent_start_sector = 7; info->granule_sectors = 4; info->first_granule_cylinder = 0; info->variant = 0; } else if (heads_per_disk == 2 && sector_length == 256 && sectors_per_track == 16) { // double-sided, double-density info->sector_size = 256; info->heads = 2; info->fat_start_sector = 2; info->fat_start_offset = 1; info->fat_sectors = 1; info->dirent_start_sector = 5; info->granule_sectors = 8; info->first_granule_cylinder = 1; info->variant = 1; } else { // invalid or unsupported format return IMGTOOLERR_CORRUPTIMAGE; } return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t process_rsdos_file(struct rsdos_dirent *ent, imgtool_image *img, imgtool_stream *destf, size_t *size) { floperr_t ferr; size_t s, lastgransize; UINT8 granule_count; unsigned char i = 0, granule; UINT8 usedmap[MAX_GRANULEMAP_SIZE]; /* Used to detect infinite loops */ UINT8 granule_map[MAX_GRANULEMAP_SIZE]; ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); memset(usedmap, 0, granule_count); lastgransize = ent->lastsectorbytes_lsb + (((int) ent->lastsectorbytes_msb) << 8); s = 0; granule = ent->first_granule; while(!usedmap[granule] && ((i = granule_map[granule]) < granule_count)) { usedmap[granule] = 1; if (destf) transfer_from_granule(img, granule, 9*256, destf); /* i is the next granule */ s += (256 * 9); granule = i; } if ((i < 0xc0) || (i > 0xc9)) return IMGTOOLERR_CORRUPTIMAGE; if (lastgransize) i--; lastgransize += (256 * (i - 0xc0)); if (destf) transfer_from_granule(img, granule, lastgransize, destf); if (size) *size = s + lastgransize; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_create(imgtool_image *image, imgtool_stream *f, option_resolution *opts) { floperr_t ferr; imgtoolerr_t err = IMGTOOLERR_SUCCESS; struct imgtool_floppy_image *fimg; const imgtool_class *imgclass; const struct FloppyFormat *format; imgtoolerr_t (*create)(imgtool_image *, imgtool_stream *, option_resolution *); imgtoolerr_t (*open)(imgtool_image *image, imgtool_stream *f); fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(image); imgclass = &imgtool_image_module(image)->imgclass; format = (const struct FloppyFormat *) imgclass->derived_param; create = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *, option_resolution *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_CREATE); open = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN); /* open up the floppy */ ferr = floppy_create(f, &imgtool_ioprocs, format, opts, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); goto done; } /* do we have to do extra stuff when creating the image? */ if (create) { err = create(image, NULL, opts); if (err) goto done; } /* do we have to do extra stuff when opening the image? */ if (open) { err = open(image, NULL); if (err) goto done; } done: return err; }
static imgtoolerr_t rsdos_diskimage_freespace(imgtool::partition &partition, uint64_t *size) { floperr_t ferr; uint8_t i; size_t s = 0; uint8_t granule_count; uint8_t granule_map[MAX_GRANULEMAP_SIZE]; imgtool::image &image(partition.image()); 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; }
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; }
static imgtoolerr_t imgtool_floppy_create(imgtool_image *image, imgtool_stream *f, option_resolution *opts) { floperr_t ferr; imgtoolerr_t err = IMGTOOLERR_SUCCESS; const struct FloppyFormat *format; const struct ImgtoolFloppyExtra *extra; struct imgtool_floppy_image *fimg; extra = get_extra(img_module(image)); format = extra->format; fimg = (struct imgtool_floppy_image *) img_extrabytes(image); /* open up the floppy */ ferr = floppy_create(f, &imgtool_ioprocs, format, opts, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); goto done; } /* do we have to do extra stuff when creating the image? */ if (extra->create) { err = extra->create(image, NULL, opts); if (err) goto done; } /* do we have to do extra stuff when opening the image? */ if (extra->open) { err = extra->open(image, NULL); if (err) goto done; } done: return err; }
static imgtoolerr_t list_granules(struct bml3_dirent *ent, imgtool_image *img, struct granule_list_t *granule_list) { floperr_t ferr; UINT8 max_granules; UINT8 granule; UINT8 usedmap[MAX_GRANULEMAP_SIZE]; /* Used to detect infinite loops */ UINT8 granule_map[MAX_GRANULEMAP_SIZE]; bml3_diskinfo *info = bml3_get_diskinfo(img); ferr = get_granule_map(img, granule_map, &max_granules); if (ferr) return imgtool_floppy_error(ferr); memset(usedmap, 0, max_granules); granule = ent->first_granule; granule_list->granule_count = 0; while(!usedmap[granule] && granule < max_granules) { usedmap[granule] = 1; granule_list->granules[granule_list->granule_count++] = granule; granule = granule_map[granule]; } granule_list->last_granule_sectors = granule - 0xc0; if (info->variant == 0) { // add final incomplete sector granule_list->last_granule_sectors++; } // A value of zero (variant 1) and max (variant 0) seem to indicate a file open for writing. // Strictly speaking this means the image is corrupt, although a real system will happily read // garbage from the file. if (granule_list->last_granule_sectors > info->granule_sectors) return IMGTOOLERR_CORRUPTIMAGE; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_transfer_sector_tofrom_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f, int direction) { floperr_t err; floppy_image_legacy *floppy; void *buffer = NULL; floppy = imgtool_floppy(img); buffer = malloc(length); if (!buffer) { err = FLOPPY_ERROR_OUTOFMEMORY; goto done; } if (direction) { err = floppy_read_sector(floppy, head, track, sector, offset, buffer, length); if (err) goto done; stream_write(f, buffer, length); } else { stream_read(f, buffer, length); err = floppy_write_sector(floppy, head, track, sector, offset, buffer, length, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } err = FLOPPY_ERROR_SUCCESS; done: if (buffer) free(buffer); return imgtool_floppy_error(err); }
static imgtoolerr_t os9_diskimage_open(imgtool_image *image, imgtool_stream *stream) { imgtoolerr_t err; floperr_t ferr; os9_diskinfo *info; UINT32 track_size_in_sectors, i; //, attributes; UINT8 header[256]; UINT32 allocation_bitmap_lsns; UINT8 b, mask; info = os9_get_diskinfo(image); ferr = floppy_read_sector(imgtool_floppy(image), 0, 0, 1, 0, header, sizeof(header)); if (ferr) return imgtool_floppy_error(ferr); info->total_sectors = pick_integer_be(header, 0, 3); track_size_in_sectors = pick_integer_be(header, 3, 1); info->allocation_bitmap_bytes = pick_integer_be(header, 4, 2); info->cluster_size = pick_integer_be(header, 6, 2); info->root_dir_lsn = pick_integer_be(header, 8, 3); info->owner_id = pick_integer_be(header, 11, 2); // attributes = pick_integer_be(header, 13, 1); info->disk_id = pick_integer_be(header, 14, 2); info->format_flags = pick_integer_be(header, 16, 1); info->sectors_per_track = pick_integer_be(header, 17, 2); info->bootstrap_lsn = pick_integer_be(header, 21, 3); info->bootstrap_size = pick_integer_be(header, 24, 2); info->sector_size = pick_integer_be(header, 104, 2); info->sides = (info->format_flags & 0x01) ? 2 : 1; info->double_density = (info->format_flags & 0x02) ? 1 : 0; info->double_track = (info->format_flags & 0x04) ? 1 : 0; info->quad_track_density = (info->format_flags & 0x08) ? 1 : 0; info->octal_track_density = (info->format_flags & 0x10) ? 1 : 0; pick_string(header, 31, 32, info->name); if (info->sector_size == 0) info->sector_size = 256; /* does the root directory and allocation bitmap collide? */ allocation_bitmap_lsns = (info->allocation_bitmap_bytes + info->sector_size - 1) / info->sector_size; if (1 + allocation_bitmap_lsns > info->root_dir_lsn) return IMGTOOLERR_CORRUPTIMAGE; /* is the allocation bitmap too big? */ info->allocation_bitmap = (UINT8*)imgtool_image_malloc(image, info->allocation_bitmap_bytes); if (!info->allocation_bitmap) return IMGTOOLERR_OUTOFMEMORY; memset(info->allocation_bitmap, 0, info->allocation_bitmap_bytes); /* sectors per track and track size don't jive? */ if (info->sectors_per_track != track_size_in_sectors) return IMGTOOLERR_CORRUPTIMAGE; /* zero sectors per track? */ if (info->sectors_per_track == 0) return IMGTOOLERR_CORRUPTIMAGE; /* do we have an odd number of sectors? */ if (info->total_sectors % info->sectors_per_track) return IMGTOOLERR_CORRUPTIMAGE; /* read the allocation bitmap */ for (i = 0; i < allocation_bitmap_lsns; i++) { err = os9_read_lsn(image, 1 + i, 0, &info->allocation_bitmap[i * info->sector_size], MIN(info->allocation_bitmap_bytes - (i * info->sector_size), info->sector_size)); if (err) return err; } /* check to make sure that the allocation bitmap and root sector are reserved */ for (i = 0; i <= allocation_bitmap_lsns; i++) { b = info->allocation_bitmap[i / 8]; mask = 1 << (7 - (i % 8)); if ((b & mask) == 0) return IMGTOOLERR_CORRUPTIMAGE; } 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 rsdos_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); 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 = option_resolution_lookup_int(writeoptions, RSDOS_OPTIONS_FTYPE); ent.asciiflag = ((UINT8) option_resolution_lookup_int(writeoptions, 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 = MIN(sz, (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; }
static imgtoolerr_t rsdos_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent) { floperr_t ferr; imgtoolerr_t err; size_t filesize; struct rsdos_direnum *rsenum; struct rsdos_dirent rsent; char fname[13]; imgtool_image *image; image = imgtool_directory_image(enumeration); rsenum = (struct rsdos_direnum *) imgtool_directory_extrabytes(enumeration); /* Did we hit the end of file before? */ if (rsenum->eof) goto eof; do { if (rsenum->index >= MAX_DIRENTS) goto eof; ferr = get_rsdos_dirent(image, rsenum->index++, &rsent); if (ferr) return imgtool_floppy_error(ferr); } while(rsent.fname[0] == '\0'); /* Now are we at the eof point? */ if (rsent.fname[0] == -1) { rsenum->eof = 1; eof: ent->eof = 1; } else { /* Not the end of file */ err = process_rsdos_file(&rsent, image, NULL, &filesize); if (err) return err; if (filesize == ((size_t) -1)) { /* corrupt! */ ent->filesize = 0; ent->corrupt = 1; } else { ent->filesize = filesize; ent->corrupt = 0; } ent->eof = 0; get_dirent_fname(fname, &rsent); snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", fname); snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B')); } 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(partition.image()); struct rsdos_dirent ent, ent2; size_t i; uint64_t sz; uint64_t freespace = 0; unsigned char g; unsigned char *gptr; uint8_t granule_count; uint8_t 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 = sourcef.size(); 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_t(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_t(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.filename[0] != '\0') && strcmp(ent.filename, ent2.filename) && (ent2.filename[0] != -1)); // delete file if it already exists if (ent2.filename[0] && (ent2.filename[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; }