Example #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;
}
Example #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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
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);
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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, &sector);
	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;
}
Example #14
0
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, &sector);
	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;
}
Example #15
0
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, &sector_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;
}
Example #16
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;
}
Example #17
0
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;
}
Example #18
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;
}
Example #19
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;
}
Example #20
0
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;
}
Example #21
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;
}
Example #22
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;
	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);
}
Example #23
0
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;
}
Example #24
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;
}
Example #25
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;
}
Example #26
0
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;
}
Example #27
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;
}