[Imgtool CoCo/RS-DOS] Miscellaneous cleanups and C++ modernization

This commit is contained in:
Nathan Woods 2016-12-24 13:43:52 -05:00 committed by angelosa
parent 4f7ff8f846
commit 54766981c2
3 changed files with 165 additions and 88 deletions

View File

@ -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
//-------------------------------------------------

View File

@ -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 */

View File

@ -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;