diff options
Diffstat (limited to 'src/mess/tools/imgtool/modules/os9.c')
-rw-r--r-- | src/mess/tools/imgtool/modules/os9.c | 1244 |
1 files changed, 0 insertions, 1244 deletions
diff --git a/src/mess/tools/imgtool/modules/os9.c b/src/mess/tools/imgtool/modules/os9.c deleted file mode 100644 index 2a9e2fb0292..00000000000 --- a/src/mess/tools/imgtool/modules/os9.c +++ /dev/null @@ -1,1244 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -/**************************************************************************** - - os9.c - - CoCo OS-9 disk images - -****************************************************************************/ - -#include <time.h> - -#include "imgtool.h" -#include "formats/imageutl.h" -#include "formats/coco_dsk.h" -#include "iflopimg.h" - -enum creation_policy_t -{ - CREATE_NONE, - CREATE_FILE, - CREATE_DIR -}; - -struct os9_diskinfo -{ - UINT32 total_sectors; - UINT32 sectors_per_track; - UINT32 allocation_bitmap_bytes; - UINT32 cluster_size; - UINT32 root_dir_lsn; - UINT32 owner_id; - UINT32 attributes; - UINT32 disk_id; - UINT32 format_flags; - UINT32 bootstrap_lsn; - UINT32 bootstrap_size; - UINT32 sector_size; - - unsigned int sides : 2; - unsigned int double_density : 1; - unsigned int double_track : 1; - unsigned int quad_track_density : 1; - unsigned int octal_track_density : 1; - - char name[33]; - UINT8 *allocation_bitmap; -}; - - -struct os9_fileinfo -{ - unsigned int directory : 1; - unsigned int non_sharable : 1; - unsigned int public_execute : 1; - unsigned int public_write : 1; - unsigned int public_read : 1; - unsigned int user_execute : 1; - unsigned int user_write : 1; - unsigned int user_read : 1; - - UINT32 lsn; - UINT32 owner_id; - UINT32 link_count; - UINT32 file_size; - - struct - { - UINT32 lsn; - UINT32 count; - } sector_map[48]; -}; - - -struct os9_direnum -{ - struct os9_fileinfo dir_info; - UINT32 index; -}; - - - -static void pick_string(const void *ptr, size_t offset, size_t length, char *dest) -{ - UINT8 b; - - while(length--) - { - b = ((UINT8 *) ptr)[offset++]; - *(dest++) = b & 0x7F; - if (b & 0x80) - length = 0; - } - *dest = '\0'; -} - - - -static void place_string(void *ptr, size_t offset, size_t length, const char *s) -{ - size_t i; - UINT8 b; - UINT8 *bptr; - - bptr = (UINT8 *) ptr; - bptr += offset; - - bptr[0] = 0x80; - - for (i = 0; s[i] && (i < length); i++) - { - b = ((UINT8) s[i]) & 0x7F; - if (s[i+1] == '\0') - b |= 0x80; - bptr[i] = b; - } -} - - - -static os9_diskinfo *os9_get_diskinfo(imgtool_image *image) -{ - return (os9_diskinfo *) imgtool_floppy_extrabytes(image); -} - - - -static struct os9_direnum *os9_get_dirinfo(imgtool_directory *directory) -{ - return (struct os9_direnum *) imgtool_directory_extrabytes(directory); -} - - - -static imgtoolerr_t os9_locate_lsn(imgtool_image *image, UINT32 lsn, UINT32 *head, UINT32 *track, UINT32 *sector) -{ - const os9_diskinfo *disk_info; - - disk_info = os9_get_diskinfo(image); - if (lsn > disk_info->total_sectors) - return IMGTOOLERR_CORRUPTIMAGE; - - *track = lsn / (disk_info->sectors_per_track * disk_info->sides); - *head = (lsn / disk_info->sectors_per_track) % disk_info->sides; - *sector = (lsn % disk_info->sectors_per_track) + 1; - return IMGTOOLERR_SUCCESS; -} - - - -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, §or); - 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; -} - - - -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, §or); - 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; -} - - - -static UINT32 os9_lookup_lsn(imgtool_image *img, - const struct os9_fileinfo *file_info, UINT32 *index) -{ - int i; - UINT32 lsn; - const os9_diskinfo *disk_info; - - disk_info = os9_get_diskinfo(img); - lsn = *index / disk_info->sector_size; - - i = 0; - while(lsn >= file_info->sector_map[i].count) - lsn -= file_info->sector_map[i++].count; - - lsn = file_info->sector_map[i].lsn + lsn; - *index %= disk_info->sector_size; - return lsn; -} - - - -static int os9_interpret_dirent(void *entry, char **filename, UINT32 *lsn, int *corrupt) -{ - int i; - char *entry_b = (char *) entry; - - *filename = NULL; - *lsn = 0; - if (corrupt) - *corrupt = FALSE; - - if (entry_b[28] != '\0') - { - if (corrupt) - *corrupt = TRUE; - } - - for (i = 0; (i < 28) && !(entry_b[i] & 0x80); i++) - ; - entry_b[i] &= 0x7F; - entry_b[i+1] = '\0'; - - *lsn = pick_integer_be(entry, 29, 3); - if (strcmp(entry_b, ".") && strcmp(entry_b, "..")) - *filename = entry_b; - return *filename != NULL; -} - - - -/*------------------------------------------------- - os9_decode_file_header - reads a file/directory - entry from an LSN, and decodes it --------------------------------------------------*/ - -static imgtoolerr_t os9_decode_file_header(imgtool_image *image, - int lsn, struct os9_fileinfo *info) -{ - imgtoolerr_t err; - UINT32 attributes, count; - int max_entries, i; - const os9_diskinfo *disk_info; - UINT8 header[256]; - - disk_info = os9_get_diskinfo(image); - - err = os9_read_lsn(image, lsn, 0, header, sizeof(header)); - if (err) - return err; - - info->lsn = lsn; - attributes = pick_integer_be(header, 0, 1); - info->owner_id = pick_integer_be(header, 1, 2); - info->link_count = pick_integer_be(header, 8, 1); - info->file_size = pick_integer_be(header, 9, 4); - info->directory = (attributes & 0x80) ? 1 : 0; - info->non_sharable = (attributes & 0x40) ? 1 : 0; - info->public_execute = (attributes & 0x20) ? 1 : 0; - info->public_write = (attributes & 0x10) ? 1 : 0; - info->public_read = (attributes & 0x08) ? 1 : 0; - info->user_execute = (attributes & 0x04) ? 1 : 0; - info->user_write = (attributes & 0x02) ? 1 : 0; - info->user_read = (attributes & 0x01) ? 1 : 0; - - if (info->directory && (info->file_size % 32 != 0)) - return IMGTOOLERR_CORRUPTIMAGE; - - /* read all sector map entries */ - max_entries = (disk_info->sector_size - 16) / 5; - max_entries = MIN(max_entries, ARRAY_LENGTH(info->sector_map) - 1); - for (i = 0; i < max_entries; i++) - { - lsn = pick_integer_be(header, 16 + (i * 5) + 0, 3); - count = pick_integer_be(header, 16 + (i * 5) + 3, 2); - if (count <= 0) - break; - - info->sector_map[i].lsn = lsn; - info->sector_map[i].count = count; - } - info->sector_map[i].lsn = 0; - info->sector_map[i].count = 0; - return IMGTOOLERR_SUCCESS; -} - - - -static imgtoolerr_t os9_allocate_lsn(imgtool_image *image, UINT32 *lsn) -{ - UINT32 i; - os9_diskinfo *disk_info; - UINT8 b, mask; - - disk_info = os9_get_diskinfo(image); - - for (i = 0; i < disk_info->total_sectors; i++) - { - b = disk_info->allocation_bitmap[i / 8]; - mask = 1 << (7 - (i % 8)); - - if ((b & mask) == 0) - { - disk_info->allocation_bitmap[i / 8] |= mask; - *lsn = i; - return os9_write_lsn(image, 1, 0, disk_info->allocation_bitmap, disk_info->allocation_bitmap_bytes); - } - } - return IMGTOOLERR_NOSPACE; -} - - - -static imgtoolerr_t os9_deallocate_lsn(imgtool_image *image, UINT32 lsn) -{ - UINT8 mask; - os9_diskinfo *disk_info; - - disk_info = os9_get_diskinfo(image); - mask = 1 << (7 - (lsn % 8)); - disk_info->allocation_bitmap[lsn / 8] &= ~mask; - return os9_write_lsn(image, 1, 0, disk_info->allocation_bitmap, disk_info->allocation_bitmap_bytes); -} - - - -static UINT32 os9_get_free_lsns(imgtool_image *image) -{ - const os9_diskinfo *disk_info; - UINT32 i, free_lsns; - UINT8 b; - - disk_info = os9_get_diskinfo(image); - free_lsns = 0; - - for (i = 0; i < disk_info->total_sectors; i++) - { - b = disk_info->allocation_bitmap[i / 8]; - b >>= (7 - (i % 8)); - free_lsns += ~b & 1; - } - - return free_lsns; -} - - - -static imgtoolerr_t os9_corrupt_file_error(const struct os9_fileinfo *file_info) -{ - imgtoolerr_t err; - if (file_info->directory) - err = IMGTOOLERR_CORRUPTDIR; - else - err = IMGTOOLERR_CORRUPTFILE; - return err; -} - - - -static imgtoolerr_t os9_set_file_size(imgtool_image *image, - struct os9_fileinfo *file_info, UINT32 new_size) -{ - imgtoolerr_t err; - const os9_diskinfo *disk_info; - UINT32 new_lsn_count, current_lsn_count; - UINT32 free_lsns, lsn, i; - int sector_map_length = -1; - UINT8 header[256]; - - /* easy way out? */ - if (file_info->file_size == new_size) - return IMGTOOLERR_SUCCESS; - - disk_info = os9_get_diskinfo(image); - - free_lsns = os9_get_free_lsns(image); - current_lsn_count = (file_info->file_size + disk_info->sector_size - 1) / disk_info->sector_size; - new_lsn_count = (new_size + disk_info->sector_size - 1) / disk_info->sector_size; - - /* check to see if the file is growing and we do not have enough space */ - if ((new_lsn_count > current_lsn_count) && (new_lsn_count - current_lsn_count > free_lsns)) - return IMGTOOLERR_NOSPACE; - - if (current_lsn_count != new_lsn_count) - { - /* first find out the size of our sector map */ - sector_map_length = 0; - lsn = 0; - while((lsn < current_lsn_count) && (sector_map_length < ARRAY_LENGTH(file_info->sector_map))) - { - if (file_info->sector_map[sector_map_length].count == 0) - return os9_corrupt_file_error(file_info); - - lsn += file_info->sector_map[sector_map_length].count; - sector_map_length++; - } - - /* keep in mind that the sector_map might not parallel our expected - * current LSN count; we should tolerate this abnormality */ - current_lsn_count = lsn; - - while(current_lsn_count > new_lsn_count) - { - /* shrink this file */ - lsn = file_info->sector_map[sector_map_length - 1].lsn + - file_info->sector_map[sector_map_length - 1].count - 1; - - err = os9_deallocate_lsn(image, lsn); - if (err) - return err; - - file_info->sector_map[sector_map_length - 1].count--; - while(sector_map_length > 0 && (file_info->sector_map[sector_map_length - 1].count == 0)) - sector_map_length--; - current_lsn_count--; - } - - while(current_lsn_count < new_lsn_count) - { - /* grow this file */ - err = os9_allocate_lsn(image, &lsn); - if (err) - return err; - - if ((sector_map_length > 0) && ((file_info->sector_map[sector_map_length - 1].lsn + - file_info->sector_map[sector_map_length - 1].count) == lsn)) - { - file_info->sector_map[sector_map_length - 1].count++; - } - else if (sector_map_length >= ARRAY_LENGTH(file_info->sector_map)) - { - return IMGTOOLERR_NOSPACE; - } - else - { - file_info->sector_map[sector_map_length].lsn = lsn; - file_info->sector_map[sector_map_length].count = 1; - sector_map_length++; - file_info->sector_map[sector_map_length].lsn = 0; - file_info->sector_map[sector_map_length].count = 0; - } - current_lsn_count++; - } - } - - /* now lets write back the sector */ - err = os9_read_lsn(image, file_info->lsn, 0, header, sizeof(header)); - if (err) - return err; - - file_info->file_size = new_size; - place_integer_be(header, 9, 4, file_info->file_size); - - /* do we have to write the sector map? */ - if (sector_map_length >= 0) - { - for (i = 0; i < MIN(sector_map_length + 1, ARRAY_LENGTH(file_info->sector_map)); i++) - { - place_integer_be(header, 16 + (i * 5) + 0, 3, file_info->sector_map[i].lsn); - place_integer_be(header, 16 + (i * 5) + 3, 2, file_info->sector_map[i].count); - } - } - - err = os9_write_lsn(image, file_info->lsn, 0, header, disk_info->sector_size); - if (err) - return err; - - return IMGTOOLERR_SUCCESS; -} - - - -/*------------------------------------------------- - os9_lookup_path - walks an OS-9 directory - structure to find a file, or optionally, create - a file --------------------------------------------------*/ - -static imgtoolerr_t os9_lookup_path(imgtool_image *img, const char *path, - creation_policy_t create, struct os9_fileinfo *file_info, - UINT32 *parent_lsn, UINT32 *dirent_lsn, UINT32 *dirent_index) -{ - imgtoolerr_t err = IMGTOOLERR_SUCCESS; - struct os9_fileinfo dir_info; - UINT32 index, current_lsn, dir_size; - UINT32 entry_index = 0; - UINT32 free_entry_index = 0xffffffff; - UINT32 entry_lsn = 0; - UINT32 allocated_lsn = 0; - UINT8 entry[32]; - UINT8 block[64]; - char *filename; - const os9_diskinfo *disk_info; - - disk_info = os9_get_diskinfo(img); - current_lsn = disk_info->root_dir_lsn; - - if (parent_lsn) - *parent_lsn = 0; - - /* we have to transverse each path element */ - while(*path) - { - if (parent_lsn) - *parent_lsn = current_lsn; - - /* decode the directory header of this directory */ - err = os9_decode_file_header(img, current_lsn, &dir_info); - if (err) - goto done; - dir_size = dir_info.file_size; - - /* sanity check directory */ - if (!dir_info.directory) - { - err = (current_lsn == disk_info->root_dir_lsn) ? IMGTOOLERR_CORRUPTIMAGE : IMGTOOLERR_INVALIDPATH; - goto done; - } - - /* walk the directory */ - for (index = 0; index < dir_size; index += 32) - { - entry_index = index; - entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); - - err = os9_read_lsn(img, entry_lsn, entry_index, entry, sizeof(entry)); - if (err) - goto done; - - /* remember first free entry found */ - if( free_entry_index == 0xffffffff ) - { - if( entry[0] == 0 ) - free_entry_index = index; - } - - if (os9_interpret_dirent(entry, &filename, ¤t_lsn, NULL)) - { - if (!strcmp(path, filename)) - break; - } - - } - - /* at the end of the file? */ - if (index >= dir_size) - { - /* if we're not creating, or we are creating but we have not fully - * transversed the directory, error out */ - if (!create || path[strlen(path) + 1]) - { - err = IMGTOOLERR_PATHNOTFOUND; - goto done; - } - - /* allocate a new LSN */ - err = os9_allocate_lsn(img, &allocated_lsn); - if (err) - goto done; - - /* write the file */ - memset(block, 0, sizeof(block)); - place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00)); - err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block)); - if (err) - goto done; - - if( free_entry_index == 0xffffffff ) - { - /* expand the directory to hold the new entry */ - err = os9_set_file_size(img, &dir_info, dir_size + 32); - if (err) - goto done; - } - else - /* use first unused entry in directory */ - dir_size = free_entry_index; - - /* now prepare the directory entry */ - memset(entry, 0, sizeof(entry)); - place_string(entry, 0, 28, path); - place_integer_be(entry, 29, 3, allocated_lsn); - - /* now write the directory entry */ - entry_index = dir_size; - entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index); - err = os9_write_lsn(img, entry_lsn, entry_index, entry, 32); - if (err) - goto done; - - /* directory entry append complete; no need to hold this lsn */ - current_lsn = allocated_lsn; - allocated_lsn = 0; - } - path += strlen(path) + 1; - } - - if (file_info) - { - err = os9_decode_file_header(img, current_lsn, file_info); - if (err) - goto done; - } - - if (dirent_lsn) - *dirent_lsn = entry_lsn; - if (dirent_index) - *dirent_index = entry_index; - -done: - if (allocated_lsn != 0) - os9_deallocate_lsn(img, allocated_lsn); - return err; -} - - - -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; -} - - - -static imgtoolerr_t os9_diskimage_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts) -{ - imgtoolerr_t err; - dynamic_buffer header; - UINT32 heads, tracks, sectors, sector_bytes, first_sector_id; - UINT32 cluster_size, owner_id; - UINT32 allocation_bitmap_bits, allocation_bitmap_lsns; - UINT32 attributes, format_flags, disk_id; - UINT32 i; - INT32 total_allocated_sectors; - const char *title; - time_t t; - struct tm *ltime; - - time(&t); - ltime = localtime(&t); - - heads = option_resolution_lookup_int(opts, 'H'); - tracks = option_resolution_lookup_int(opts, 'T'); - sectors = option_resolution_lookup_int(opts, 'S'); - sector_bytes = option_resolution_lookup_int(opts, 'L'); - first_sector_id = option_resolution_lookup_int(opts, 'F'); - title = ""; - - header.resize(sector_bytes); - - if (sector_bytes > 256) - sector_bytes = 256; - cluster_size = 1; - owner_id = 1; - disk_id = 1; - attributes = 0; - allocation_bitmap_bits = heads * tracks * sectors / cluster_size; - allocation_bitmap_lsns = (allocation_bitmap_bits / 8 + sector_bytes - 1) / sector_bytes; - format_flags = ((heads > 1) ? 0x01 : 0x00) | ((tracks > 40) ? 0x02 : 0x00); - - memset(&header[0], 0, sector_bytes); - place_integer_be(&header[0], 0, 3, heads * tracks * sectors); - place_integer_be(&header[0], 3, 1, sectors); - place_integer_be(&header[0], 4, 2, (allocation_bitmap_bits + 7) / 8); - place_integer_be(&header[0], 6, 2, cluster_size); - place_integer_be(&header[0], 8, 3, 1 + allocation_bitmap_lsns); - place_integer_be(&header[0], 11, 2, owner_id); - place_integer_be(&header[0], 13, 1, attributes); - place_integer_be(&header[0], 14, 2, disk_id); - place_integer_be(&header[0], 16, 1, format_flags); - place_integer_be(&header[0], 17, 2, sectors); - place_string(&header[0], 31, 32, title); - place_integer_be(&header[0], 103, 2, sector_bytes / 256); - - /* path descriptor options */ - place_integer_be(&header[0], 0x3f+0x00, 1, 1); /* device class */ - place_integer_be(&header[0], 0x3f+0x01, 1, 1); /* drive number */ - place_integer_be(&header[0], 0x3f+0x03, 1, 0x20); /* device type */ - place_integer_be(&header[0], 0x3f+0x04, 1, 1); /* density capability */ - place_integer_be(&header[0], 0x3f+0x05, 2, tracks); /* number of tracks */ - place_integer_be(&header[0], 0x3f+0x07, 1, heads); /* number of sides */ - place_integer_be(&header[0], 0x3f+0x09, 2, sectors); /* sectors per track */ - place_integer_be(&header[0], 0x3f+0x0b, 2, sectors); /* sectors on track zero */ - place_integer_be(&header[0], 0x3f+0x0d, 1, 3); /* sector interleave factor */ - place_integer_be(&header[0], 0x3f+0x0e, 1, 8); /* default sectors per allocation */ - - err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ - if (err) - goto done; - - total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 7; - - for (i = 0; i < allocation_bitmap_lsns; i++) - { - memset(&header[0], 0x00, sector_bytes); - - if (total_allocated_sectors > (8 * 256)) - { - memset(&header[0], 0xff, sector_bytes); - total_allocated_sectors -= (8 * 256); - } - else if (total_allocated_sectors > 1 ) - { - int offset; - UINT8 mask; - - while( total_allocated_sectors >= 0 ) - { - offset = total_allocated_sectors / 8; - mask = 1 << (7 - ( total_allocated_sectors % 8 ) ); - - header[offset] |= mask; - total_allocated_sectors--; - } - } - - err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + i, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ - if (err) - goto done; - } - - memset(&header[0], 0, sector_bytes); - header[0x00] = 0xBF; - header[0x01] = 0x00; - header[0x02] = 0x00; - header[0x03] = (UINT8) ltime->tm_year; - header[0x04] = (UINT8) ltime->tm_mon + 1; - header[0x05] = (UINT8) ltime->tm_mday; - header[0x06] = (UINT8) ltime->tm_hour; - header[0x07] = (UINT8) ltime->tm_min; - header[0x08] = 0x02; - header[0x09] = 0x00; - header[0x0A] = 0x00; - header[0x0B] = 0x00; - header[0x0C] = 0x40; - header[0x0D] = (UINT8) (ltime->tm_year % 100); - header[0x0E] = (UINT8) ltime->tm_mon; - header[0x0F] = (UINT8) ltime->tm_mday; - place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1); - place_integer_be(&header[0], 0x13, 2, 8); - - err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ - if (err) - goto done; - - memset(&header[0], 0, sector_bytes); - header[0x00] = 0x2E; - header[0x01] = 0xAE; - header[0x1F] = 1 + allocation_bitmap_lsns; - header[0x20] = 0xAE; - header[0x3F] = 1 + allocation_bitmap_lsns; - err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 2 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TOOD: pass ddam argument from imgtool */ - if (err) - goto done; - -done: - return err; -} - - - -static imgtoolerr_t os9_diskimage_beginenum(imgtool_directory *enumeration, const char *path) -{ - imgtoolerr_t err = IMGTOOLERR_SUCCESS; - struct os9_direnum *os9enum; - imgtool_image *image; - - image = imgtool_directory_image(enumeration); - os9enum = os9_get_dirinfo(enumeration); - - err = os9_lookup_path(image, path, CREATE_NONE, &os9enum->dir_info, NULL, NULL, NULL); - if (err) - goto done; - - /* this had better be a directory */ - if (!os9enum->dir_info.directory) - { - err = IMGTOOLERR_CORRUPTIMAGE; - goto done; - } - -done: - return err; -} - - - -static imgtoolerr_t os9_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent) -{ - struct os9_direnum *os9enum; - UINT32 lsn, index; - imgtoolerr_t err; - UINT8 dir_entry[32]; - char filename[29]; - struct os9_fileinfo file_info; - imgtool_image *image; - - image = imgtool_directory_image(enumeration); - os9enum = os9_get_dirinfo(enumeration); - - do - { - /* check for EOF */ - if (os9enum->index >= os9enum->dir_info.file_size) - { - ent->eof = 1; - return IMGTOOLERR_SUCCESS; - } - - /* locate the LSN and offset for this directory entry */ - index = os9enum->index; - lsn = os9_lookup_lsn(image, &os9enum->dir_info, &index); - - /* read the directory entry out of the lSN */ - err = os9_read_lsn(image, lsn, index, dir_entry, sizeof(dir_entry)); - if (err) - return err; - - if (dir_entry[0]) - { - /* read the file or directory name */ - pick_string(dir_entry, 0, 28, filename); - - /* we have certain expectations of the directory contents; the - * first directory entry should be "..", the second ".", and - * subsequent entries should never be "." or ".." */ - switch(os9enum->index) - { - case 0: - if (strcmp(filename, "..")) - imgtool_warn("First entry in directory should be \"..\" and not \"%s\"", filename); - break; - - case 32: - if (strcmp(filename, ".")) - imgtool_warn("Second entry in directory should be \".\" and not \"%s\"", filename); - break; - - default: - if (!strcmp(filename, ".") || !strcmp(filename, "..")) - imgtool_warn("Directory entry %d should not be \"%s\"", index / 32, filename); - break; - } - - /* if the filename is ".", the file should point to the current directory */ - if (!strcmp(filename, ".") && (pick_integer_be(dir_entry, 29, 3) != os9enum->dir_info.lsn)) - { - imgtool_warn("Directory \".\" does not point back to same directory"); - } - } - else - { - /* no more directory entries */ - filename[0] = '\0'; - } - - /* move on to the next directory entry */ - os9enum->index += 32; - } - while(!filename[0] || !strcmp(filename, ".") || !strcmp(filename, "..")); - - /* read file attributes */ - lsn = pick_integer_be(dir_entry, 29, 3); - err = os9_decode_file_header(imgtool_directory_image(enumeration), lsn, &file_info); - if (err) - return err; - - /* fill out imgtool_dirent structure */ - snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", filename); - snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%c%c%c%c%c%c%c%c", - file_info.directory ? 'd' : '-', - file_info.non_sharable ? 's' : '-', - file_info.public_execute ? 'x' : '-', - file_info.public_write ? 'w' : '-', - file_info.public_read ? 'r' : '-', - file_info.user_execute ? 'x' : '-', - file_info.user_write ? 'w' : '-', - file_info.user_read ? 'r' : '-'); - - ent->directory = file_info.directory; - ent->corrupt = (dir_entry[28] != 0); - ent->filesize = file_info.file_size; - return IMGTOOLERR_SUCCESS; -} - - - -static imgtoolerr_t os9_diskimage_freespace(imgtool_partition *partition, UINT64 *size) -{ - imgtool_image *image = imgtool_partition_image(partition); - const os9_diskinfo *disk_info; - UINT32 free_lsns; - - disk_info = os9_get_diskinfo(image); - free_lsns = os9_get_free_lsns(image); - - *size = free_lsns * disk_info->sector_size; - return IMGTOOLERR_SUCCESS; -} - - - -static imgtoolerr_t os9_diskimage_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf) -{ - imgtoolerr_t err; - imgtool_image *img = imgtool_partition_image(partition); - const os9_diskinfo *disk_info; - struct os9_fileinfo file_info; - UINT8 buffer[256]; - int i, j; - UINT32 file_size; - UINT32 used_size; - - disk_info = os9_get_diskinfo(img); - - err = os9_lookup_path(img, filename, CREATE_NONE, &file_info, NULL, NULL, NULL); - if (err) - return err; - if (file_info.directory) - return IMGTOOLERR_FILENOTFOUND; - file_size = file_info.file_size; - - for (i = 0; file_info.sector_map[i].count > 0; i++) - { - for (j = 0; j < file_info.sector_map[i].count; j++) - { - used_size = MIN(file_size, disk_info->sector_size); - err = os9_read_lsn(img, file_info.sector_map[i].lsn + j, 0, - buffer, used_size); - if (err) - return err; - stream_write(destf, buffer, used_size); - file_size -= used_size; - } - } - return IMGTOOLERR_SUCCESS; -} - - - -static imgtoolerr_t os9_diskimage_writefile(imgtool_partition *partition, const char *path, const char *fork, imgtool_stream *sourcef, option_resolution *opts) -{ - imgtoolerr_t err; - imgtool_image *image = imgtool_partition_image(partition); - struct os9_fileinfo file_info; - size_t write_size; - dynamic_buffer buf; - int i = -1; - UINT32 lsn = 0; - UINT32 count = 0; - UINT32 sz; - const os9_diskinfo *disk_info; - - disk_info = os9_get_diskinfo(image); - - buf.resize(disk_info->sector_size); - - err = os9_lookup_path(image, path, CREATE_FILE, &file_info, NULL, NULL, NULL); - if (err) - goto done; - - sz = (UINT32) stream_size(sourcef); - - err = os9_set_file_size(image, &file_info, sz); - if (err) - goto done; - - while(sz > 0) - { - write_size = (size_t) MIN(sz, (UINT64) disk_info->sector_size); - - stream_read(sourcef, &buf[0], write_size); - - while(count == 0) - { - i++; - lsn = file_info.sector_map[i].lsn; - count = file_info.sector_map[i].count; - } - - err = os9_write_lsn(image, lsn, 0, &buf[0], write_size); - if (err) - goto done; - - lsn++; - count--; - sz -= write_size; - } - -done: - return err; -} - - - -static imgtoolerr_t os9_diskimage_delete(imgtool_partition *partition, const char *path, - unsigned int delete_directory) -{ - imgtoolerr_t err; - imgtool_image *image = imgtool_partition_image(partition); - //const os9_diskinfo *disk_info; - struct os9_fileinfo file_info; - UINT32 dirent_lsn, dirent_index; - UINT32 entry_lsn, entry_index; - UINT32 i, j, lsn; - UINT8 b; - - //disk_info = os9_get_diskinfo(image); - - err = os9_lookup_path(image, path, CREATE_NONE, &file_info, NULL, &dirent_lsn, &dirent_index); - if (err) - return err; - if (file_info.directory != delete_directory) - return IMGTOOLERR_FILENOTFOUND; - - /* make sure that if we are deleting a directory, it is empty */ - if (delete_directory) - { - for (i = 64; i < file_info.file_size; i += 32) - { - entry_index = i; - entry_lsn = os9_lookup_lsn(image, &file_info, &entry_index); - - err = os9_read_lsn(image, entry_lsn, entry_index, &b, 1); - if (err) - return err; - - /* this had better be a deleted file, if not we can't delete */ - if (b != 0) - return IMGTOOLERR_DIRNOTEMPTY; - } - } - - /* zero out the file entry */ - b = '\0'; - err = os9_write_lsn(image, dirent_lsn, dirent_index, &b, 1); - if (err) - return err; - - /* get the link count */ - err = os9_read_lsn(image, file_info.lsn, 8, &b, 1); - if (err) - return err; - - if (b > 0) - b--; - if (b > 0) - { - /* link count is greater than zero */ - err = os9_write_lsn(image, file_info.lsn, 8, &b, 1); - if (err) - return err; - } - else - { - /* no more links; outright delete the file */ - err = os9_deallocate_lsn(image, file_info.lsn); - if (err) - return err; - - for (i = 0; (i < ARRAY_LENGTH(file_info.sector_map)) && file_info.sector_map[i].count; i++) - { - lsn = file_info.sector_map[i].lsn; - for (j = 0; j < file_info.sector_map[i].count; j++) - { - err = os9_deallocate_lsn(image, lsn + j); - if (err) - return err; - } - } - } - - return IMGTOOLERR_SUCCESS; -} - - - -static imgtoolerr_t os9_diskimage_deletefile(imgtool_partition *partition, const char *path) -{ - return os9_diskimage_delete(partition, path, 0); -} - - - -static imgtoolerr_t os9_diskimage_createdir(imgtool_partition *partition, const char *path) -{ - imgtoolerr_t err; - imgtool_image *image = imgtool_partition_image(partition); - struct os9_fileinfo file_info; - UINT8 dir_data[64]; - UINT32 parent_lsn; - - err = os9_lookup_path(image, path, CREATE_DIR, &file_info, &parent_lsn, NULL, NULL); - if (err) - goto done; - - err = os9_set_file_size(image, &file_info, 64); - if (err) - goto done; - - /* create intial directories */ - memset(dir_data, 0, sizeof(dir_data)); - place_string(dir_data, 0, 32, ".."); - place_integer_be(dir_data, 29, 3, parent_lsn); - place_string(dir_data, 32, 32, "."); - place_integer_be(dir_data, 61, 3, file_info.lsn); - - err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data)); - if (err) - goto done; - -done: - return err; -} - - - -static imgtoolerr_t os9_diskimage_deletedir(imgtool_partition *partition, const char *path) -{ - return os9_diskimage_delete(partition, path, 1); -} - - - -void os9_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info) -{ - switch(state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR: info->i = 1; break; - case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break; - case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(os9_diskinfo); break; - case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct os9_direnum); break; - case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "os9"); break; - case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "OS-9 format"); break; - case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break; - case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case IMGTOOLINFO_PTR_MAKE_CLASS: info->make_class = imgtool_floppy_make_class; break; - case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = os9_diskimage_create; break; - case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = os9_diskimage_open; break; - case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = os9_diskimage_beginenum; break; - case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = os9_diskimage_nextenum; break; - case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = os9_diskimage_freespace; break; - case IMGTOOLINFO_PTR_READ_FILE: info->read_file = os9_diskimage_readfile; break; - case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = os9_diskimage_writefile; break; - case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = os9_diskimage_deletefile; break; - case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = os9_diskimage_createdir; break; - case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = os9_diskimage_deletedir; break; - case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break; - } -} |