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; }
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 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; }
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, 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; }