Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}