From 54766981c284590bbc253c24d41b0f27eb3d9b89 Mon Sep 17 00:00:00 2001 From: Nathan Woods Date: Sat, 24 Dec 2016 13:43:52 -0500 Subject: [PATCH] [Imgtool CoCo/RS-DOS] Miscellaneous cleanups and C++ modernization --- src/tools/imgtool/imgtool.cpp | 37 +++++ src/tools/imgtool/imgtool.h | 1 + src/tools/imgtool/modules/rsdos.cpp | 215 ++++++++++++++++------------ 3 files changed, 165 insertions(+), 88 deletions(-) diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp index bb7e6c860db..3eb836b6ce3 100644 --- a/src/tools/imgtool/imgtool.cpp +++ b/src/tools/imgtool/imgtool.cpp @@ -41,6 +41,11 @@ void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...) Imgtool initialization and basics ***************************************************************************/ + +//------------------------------------------------- +// rtrim +//------------------------------------------------- + void rtrim(char *buf) { size_t buflen; @@ -54,6 +59,11 @@ void rtrim(char *buf) } } + +//------------------------------------------------- +// strncpyz +//------------------------------------------------- + char *strncpyz(char *dest, const char *source, size_t len) { char *s; @@ -67,6 +77,33 @@ char *strncpyz(char *dest, const char *source, size_t len) return s; } + +//------------------------------------------------- +// extract_padded_string +//------------------------------------------------- + +static std::string extract_padded_string(const char *source, size_t len) +{ + while ((len > 0) && (source[len - 1] == ' ')) + len--; + return std::string(source, len); +} + + +//------------------------------------------------- +// extract_padded_filename - this is a common +// enough scenario that it is justified to have +// this in common code +//------------------------------------------------- + +std::string extract_padded_filename(const char *source, size_t filename_length, size_t extension_length) +{ + std::string filename = extract_padded_string(source, filename_length); + std::string extension = extract_padded_string(source + filename_length, extension_length); + return extension.empty() ? filename : filename + "." + extension; +} + + //------------------------------------------------- // markerrorsource - marks where an error source //------------------------------------------------- diff --git a/src/tools/imgtool/imgtool.h b/src/tools/imgtool/imgtool.h index eb614a9dabb..5640b3cab12 100644 --- a/src/tools/imgtool/imgtool.h +++ b/src/tools/imgtool/imgtool.h @@ -266,5 +266,6 @@ void unknown_partition_get_info(const imgtool_class *imgclass, uint32_t state, u char *strncpyz(char *dest, const char *source, size_t len); void rtrim(char *buf); +std::string extract_padded_filename(const char *source, size_t filename_length, size_t extension_length); #endif /* IMGTOOL_H */ diff --git a/src/tools/imgtool/modules/rsdos.cpp b/src/tools/imgtool/modules/rsdos.cpp index 8be6458e45c..9ee8de3cf8c 100644 --- a/src/tools/imgtool/modules/rsdos.cpp +++ b/src/tools/imgtool/modules/rsdos.cpp @@ -2,7 +2,7 @@ // copyright-holders:Nathan Woods /**************************************************************************** - rsdos.c + rsdos.cpp CoCo RS-DOS disk images @@ -18,8 +18,7 @@ /* this structure mirrors the structure of an RS-DOS directory entry on disk */ struct rsdos_dirent { - char fname[8]; - char fext[3]; + char filename[11]; char ftype; char asciiflag; unsigned char first_granule; @@ -31,7 +30,7 @@ struct rsdos_dirent struct rsdos_direnum { int index; - int eof; + bool eof; }; #define RSDOS_OPTIONS_FTYPE 'T' @@ -44,50 +43,51 @@ struct rsdos_direnum *********************************************************************/ #define MAX_DIRENTS ((18-2)*(256/32)) -static floperr_t get_rsdos_dirent(imgtool::image &f, int index_loc, struct rsdos_dirent *ent) +#define MAX_GRANULEMAP_SIZE 256 + +//------------------------------------------------- +// get_rsdos_dirent +//------------------------------------------------- + +static floperr_t get_rsdos_dirent(imgtool::image &f, int index_loc, rsdos_dirent &ent) { - return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) ent, sizeof(*ent)); + return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent)); } +//------------------------------------------------- +// put_rsdos_dirent +//------------------------------------------------- -static floperr_t put_rsdos_dirent(imgtool::image &f, int index_loc, const struct rsdos_dirent *ent) +static floperr_t put_rsdos_dirent(imgtool::image &f, int index_loc, const rsdos_dirent &ent) { if (index_loc >= MAX_DIRENTS) return (floperr_t)IMGTOOLERR_FILENOTFOUND; - return floppy_write_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) ent, sizeof(*ent), 0); /* TODO: pass ddam argument from imgtool */ + return floppy_write_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent), 0); /* TODO: pass ddam argument from imgtool */ } +//------------------------------------------------- +// get_dirent_fname +//------------------------------------------------- -/* fnamebuf must have at least 13 bytes */ -static void get_dirent_fname(char *fnamebuf, const struct rsdos_dirent *ent) +static std::string get_dirent_fname(const rsdos_dirent &ent) { - char *s; - - memset(fnamebuf, 0, 13); - memcpy(fnamebuf, ent->fname, sizeof(ent->fname)); - rtrim(fnamebuf); - s = fnamebuf + strlen(fnamebuf); - *(s++) = '.'; - memcpy(s, ent->fext, sizeof(ent->fext)); - rtrim(s); - - /* If no extension, remove period */ - if (*s == '\0') - s[-1] = '\0'; + return extract_padded_filename(ent.filename, 8, 3); } +//------------------------------------------------- +// lookup_rsdos_file +//------------------------------------------------- -static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, struct rsdos_dirent *ent, int *position) +static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, rsdos_dirent &ent, int *position = nullptr) { int i; floperr_t ferr; - char fnamebuf[13]; + std::string fnamebuf; i = 0; - fnamebuf[0] = '\0'; do { @@ -97,15 +97,15 @@ static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, stru if (ferr) return imgtool_floppy_error(ferr); } - while(ent->fname[0] == '\0'); + while(ent.filename[0] == '\0'); - if (ent->fname[0] != -1) - get_dirent_fname(fnamebuf, ent); + if (ent.filename[0] != -1) + fnamebuf = get_dirent_fname(ent); } - while((ent->fname[0] != -1) && core_stricmp(fnamebuf, fname)); + while((ent.filename[0] != -1) && core_stricmp(fnamebuf.c_str(), fname)); - if (ent->fname[0] == -1) + if (ent.filename[0] == -1) return IMGTOOLERR_FILENOTFOUND; if (position) @@ -114,6 +114,9 @@ static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, stru } +//------------------------------------------------- +// get_granule_count +//------------------------------------------------- static uint8_t get_granule_count(imgtool::image &img) { @@ -125,10 +128,12 @@ static uint8_t get_granule_count(imgtool::image &img) return (granules > 255) ? 255 : (uint8_t) granules; } -#define MAX_GRANULEMAP_SIZE 256 -/* granule_map must be an array of MAX_GRANULEMAP_SIZE bytes */ -static floperr_t get_granule_map(imgtool::image &img, uint8_t *granule_map, uint8_t *granule_count) +//------------------------------------------------- +// get_granule_map +//------------------------------------------------- + +static floperr_t get_granule_map(imgtool::image &img, uint8_t *granule_map, uint8_t granule_count[MAX_GRANULEMAP_SIZE]) { uint8_t count; @@ -140,6 +145,9 @@ static floperr_t get_granule_map(imgtool::image &img, uint8_t *granule_map, uint } +//------------------------------------------------- +// put_granule_map +//------------------------------------------------- static floperr_t put_granule_map(imgtool::image &img, const uint8_t *granule_map, uint8_t granule_count) { @@ -147,7 +155,9 @@ static floperr_t put_granule_map(imgtool::image &img, const uint8_t *granule_map } - +//------------------------------------------------- +// transfer_granule +//------------------------------------------------- static imgtoolerr_t transfer_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &f, imgtoolerr_t (*proc)(imgtool::image &, int, int, int, int, size_t, imgtool::stream &)) { @@ -166,6 +176,9 @@ static imgtoolerr_t transfer_granule(imgtool::image &img, uint8_t granule, int l } +//------------------------------------------------- +// transfer_from_granule +//------------------------------------------------- static imgtoolerr_t transfer_from_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &destf) { @@ -173,6 +186,9 @@ static imgtoolerr_t transfer_from_granule(imgtool::image &img, uint8_t granule, } +//------------------------------------------------- +// transfer_to_granule +//------------------------------------------------- static imgtoolerr_t transfer_to_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &sourcef) { @@ -180,14 +196,17 @@ static imgtoolerr_t transfer_to_granule(imgtool::image &img, uint8_t granule, in } +//------------------------------------------------- +// process_rsdos_file +//------------------------------------------------- -static imgtoolerr_t process_rsdos_file(struct rsdos_dirent *ent, imgtool::image &img, imgtool::stream *destf, size_t *size) +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_t granule_count; unsigned char i = 0, granule; - uint8_t usedmap[MAX_GRANULEMAP_SIZE]; /* Used to detect infinite loops */ + uint8_t usedmap[MAX_GRANULEMAP_SIZE]; // used to detect infinite loops uint8_t granule_map[MAX_GRANULEMAP_SIZE]; ferr = get_granule_map(img, granule_map, &granule_count); @@ -221,23 +240,24 @@ static imgtoolerr_t process_rsdos_file(struct rsdos_dirent *ent, imgtool::image if (destf) transfer_from_granule(img, granule, lastgransize, *destf); - if (size) - *size = s + lastgransize; + size = s + lastgransize; return IMGTOOLERR_SUCCESS; } +//------------------------------------------------- +// prepare_dirent - create a new directory entry +// with a specified name +//------------------------------------------------- -/* create a new directory entry with a specified name */ -static imgtoolerr_t prepare_dirent(struct rsdos_dirent *ent, const char *fname) +static imgtoolerr_t prepare_dirent(rsdos_dirent &ent, const char *fname) { const char *fname_end; const char *fname_ext; int fname_ext_len; - memset(ent, '\0', sizeof(*ent)); - memset(ent->fname, ' ', sizeof(ent->fname)); - memset(ent->fext, ' ', sizeof(ent->fext)); + memset(&ent, '\0', sizeof(ent)); + memset(ent.filename, ' ', sizeof(ent.filename)); fname_end = strchr(fname, '.'); if (fname_end) @@ -247,32 +267,34 @@ static imgtoolerr_t prepare_dirent(struct rsdos_dirent *ent, const char *fname) fname_ext_len = strlen(fname_ext); - /* We had better be an 8.3 filename */ + // we had better be an 8.3 filename if (((fname_end - fname) > 8) || (fname_ext_len > 3)) return IMGTOOLERR_BADFILENAME; - memcpy(ent->fname, fname, fname_end - fname); - memcpy(ent->fext, fname_ext, fname_ext_len); + memcpy(&ent.filename[0], fname, fname_end - fname); + memcpy(&ent.filename[8], fname_ext, fname_ext_len); - /* For now, all files are type 2 binary files */ - ent->ftype = 2; - ent->asciiflag = 0; + // for now, all files are type 2 binary files + ent.ftype = 2; + ent.asciiflag = 0; return IMGTOOLERR_SUCCESS; } +//------------------------------------------------- +// rsdos_diskimage_nextenum +//------------------------------------------------- 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]; + rsdos_direnum *rsenum; + rsdos_dirent rsent; imgtool::image &image(enumeration.image()); - rsenum = (struct rsdos_direnum *) enumeration.extra_bytes(); + rsenum = (rsdos_direnum *) enumeration.extra_bytes(); /* Did we hit the end of file before? */ if (rsenum->eof) @@ -283,14 +305,14 @@ static imgtoolerr_t rsdos_diskimage_nextenum(imgtool::directory &enumeration, im if (rsenum->index >= MAX_DIRENTS) goto eof; - ferr = get_rsdos_dirent(image, rsenum->index++, &rsent); + ferr = get_rsdos_dirent(image, rsenum->index++, rsent); if (ferr) return imgtool_floppy_error(ferr); } - while(rsent.fname[0] == '\0'); + while(rsent.filename[0] == '\0'); - /* Now are we at the eof point? */ - if (rsent.fname[0] == -1) + // now are we at the eof point? + if (rsent.filename[0] == -1) { rsenum->eof = 1; eof: @@ -299,7 +321,7 @@ eof: else { /* Not the end of file */ - err = process_rsdos_file(&rsent, image, nullptr, &filesize); + err = process_rsdos_file(&rsent, image, nullptr, filesize); if (err) return err; @@ -316,15 +338,18 @@ eof: } ent.eof = 0; - get_dirent_fname(fname, &rsent); + std::string fname = get_dirent_fname(rsent); - snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fname); + 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; } +//------------------------------------------------- +// rsdos_diskimage_freespace +//------------------------------------------------- static imgtoolerr_t rsdos_diskimage_freespace(imgtool::partition &partition, uint64_t *size) { @@ -349,16 +374,19 @@ static imgtoolerr_t rsdos_diskimage_freespace(imgtool::partition &partition, uin } +//------------------------------------------------- +// delete_entry +//------------------------------------------------- -static imgtoolerr_t delete_entry(imgtool::image &img, struct rsdos_dirent *ent, int pos) +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->fname[0] = 0; + // 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); @@ -367,8 +395,8 @@ static imgtoolerr_t delete_entry(imgtool::image &img, struct rsdos_dirent *ent, if (ferr) return imgtool_floppy_error(ferr); - /* Now free up the granules */ - g = ent->first_granule; + // now free up the granules + g = ent.first_granule; while (g < granule_count) { i = granule_map[g]; @@ -384,6 +412,9 @@ static imgtoolerr_t delete_entry(imgtool::image &img, struct rsdos_dirent *ent, } +//------------------------------------------------- +// rsdos_diskimage_readfile +//------------------------------------------------- static imgtoolerr_t rsdos_diskimage_readfile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &destf) { @@ -392,11 +423,11 @@ static imgtoolerr_t rsdos_diskimage_readfile(imgtool::partition &partition, cons size_t size; imgtool::image &img(partition.image()); - err = lookup_rsdos_file(img, fname, &ent, NULL); + err = lookup_rsdos_file(img, fname, ent); if (err) return err; - err = process_rsdos_file(&ent, img, &destf, &size); + err = process_rsdos_file(&ent, img, &destf, size); if (err) return err; @@ -407,6 +438,9 @@ static imgtoolerr_t rsdos_diskimage_readfile(imgtool::partition &partition, cons } +//------------------------------------------------- +// rsdos_diskimage_writefile +//------------------------------------------------- static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions) { @@ -422,7 +456,7 @@ static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, con uint8_t granule_count; uint8_t granule_map[MAX_GRANULEMAP_SIZE]; - /* can we write to this image? */ + // can we write to this image? if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; @@ -430,13 +464,13 @@ static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, con if (err) return err; - /* is there enough space? */ + // is there enough space? sz = sourcef.size(); if (sz > freespace) return IMGTOOLERR_NOSPACE; - /* setup our directory entry */ - err = prepare_dirent(&ent, fname); + // setup our directory entry + err = prepare_dirent(ent, fname); if (err) return err; @@ -458,7 +492,7 @@ static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, con { g++; if ((g >= granule_count) || (g == 0)) - return IMGTOOLERR_UNEXPECTED; /* We should have already verified that there is enough space */ + return IMGTOOLERR_UNEXPECTED; // we should have already verified that there is enough space } *gptr = g; gptr = &granule_map[g]; @@ -471,39 +505,38 @@ static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, con sz -= i; - /* Go to next granule */ + // 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 - */ + // 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 */ + // now we need to find an empty directory entry i = -1; do { - ferr = get_rsdos_dirent(img, ++i, &ent2); + 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)); + while((ent2.filename[0] != '\0') && strcmp(ent.filename, ent2.filename) && (ent2.filename[0] != -1)); - /* delete file if it already exists */ - if (ent2.fname[0] && (ent2.fname[0] != -1)) + // delete file if it already exists + if (ent2.filename[0] && (ent2.filename[0] != -1)) { - err = delete_entry(img, &ent2, i); + err = delete_entry(img, ent2, i); if (err) return err; } - ferr = put_rsdos_dirent(img, i, &ent); + ferr = put_rsdos_dirent(img, i, ent); if (ferr) return imgtool_floppy_error(ferr); - /* write the granule map back out */ + // write the granule map back out ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); @@ -512,6 +545,9 @@ static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, con } +//------------------------------------------------- +// rsdos_diskimage_deletefile +//------------------------------------------------- static imgtoolerr_t rsdos_diskimage_deletefile(imgtool::partition &partition, const char *fname) { @@ -520,14 +556,17 @@ static imgtoolerr_t rsdos_diskimage_deletefile(imgtool::partition &partition, co int pos; struct rsdos_dirent ent; - err = lookup_rsdos_file(image, fname, &ent, &pos); + err = lookup_rsdos_file(image, fname, ent, &pos); if (err) return err; - return delete_entry(image, &ent, pos); + return delete_entry(image, ent, pos); } +//------------------------------------------------- +// rsdos_diskimage_suggesttransfer +//------------------------------------------------- static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length) { @@ -538,7 +577,7 @@ static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partitio if (fname) { - err = lookup_rsdos_file(image, fname, &ent, &pos); + err = lookup_rsdos_file(image, fname, ent, &pos); if (err) return err;