summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools/imgtool/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/imgtool/modules')
-rw-r--r--src/tools/imgtool/modules/amiga.cpp275
-rw-r--r--src/tools/imgtool/modules/bml3.cpp52
-rw-r--r--src/tools/imgtool/modules/concept.cpp21
-rw-r--r--src/tools/imgtool/modules/cybiko.cpp57
-rw-r--r--src/tools/imgtool/modules/cybikoxt.cpp42
-rw-r--r--src/tools/imgtool/modules/dgndos.cpp1256
-rw-r--r--src/tools/imgtool/modules/fat.cpp177
-rw-r--r--src/tools/imgtool/modules/fat.h3
-rw-r--r--src/tools/imgtool/modules/hp48.cpp2
-rw-r--r--src/tools/imgtool/modules/hp85_tape.cpp83
-rw-r--r--src/tools/imgtool/modules/hp9845_tape.cpp84
-rw-r--r--src/tools/imgtool/modules/mac.cpp6439
-rw-r--r--src/tools/imgtool/modules/macbin.cpp381
-rw-r--r--src/tools/imgtool/modules/macutil.cpp116
-rw-r--r--src/tools/imgtool/modules/macutil.h43
-rw-r--r--src/tools/imgtool/modules/os9.cpp158
-rw-r--r--src/tools/imgtool/modules/pc_flop.cpp25
-rw-r--r--src/tools/imgtool/modules/pc_hard.cpp67
-rw-r--r--src/tools/imgtool/modules/prodos.cpp2267
-rw-r--r--src/tools/imgtool/modules/psion.cpp19
-rw-r--r--src/tools/imgtool/modules/rsdos.cpp45
-rw-r--r--src/tools/imgtool/modules/rt11.cpp33
-rw-r--r--src/tools/imgtool/modules/thomson.cpp249
-rw-r--r--src/tools/imgtool/modules/ti99.cpp113
-rw-r--r--src/tools/imgtool/modules/ti990hd.cpp145
-rw-r--r--src/tools/imgtool/modules/vzdos.cpp211
26 files changed, 2136 insertions, 10227 deletions
diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp
index c1c5563012e..fcf1bd779a6 100644
--- a/src/tools/imgtool/modules/amiga.cpp
+++ b/src/tools/imgtool/modules/amiga.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/****************************************************************************
@@ -13,14 +13,17 @@
Includes
*****************************************************************************/
-
-#include <time.h>
-#include <string.h>
-#include <ctype.h>
-
#include "imgtool.h"
+#include "charconv.h"
#include "iflopimg.h"
-#include "formats/imageutl.h"
+
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cctype>
+#include <cstring>
+#include <ctime>
@@ -252,15 +255,22 @@ static int intl_toupper(int c)
/* Amiga filename case insensitive string compare */
-static int intl_stricmp(const char *s1, const char *s2)
+static int intl_stricmp(std::string_view s1, std::string_view s2)
{
- for (;;)
+ auto s1_iter = s1.begin();
+ auto s2_iter = s2.begin();
+ while (true)
{
- int c1 = intl_toupper(*s1++);
- int c2 = intl_toupper(*s2++);
+ if (s1.end() == s1_iter)
+ return (s2.end() == s2_iter) ? 0 : -1;
+ else if (s2.end() == s2_iter)
+ return 1;
- if (c1 == 0 || c1 != c2)
- return c1 - c2;
+ const int c1 = intl_toupper(uint8_t(*s1_iter++));
+ const int c2 = intl_toupper(uint8_t(*s2_iter++));
+ const int diff = c1 - c2;
+ if (diff)
+ return diff;
}
}
@@ -388,7 +398,7 @@ static uint32_t block_checksum(uint8_t *buffer, int length)
for (i = 0; i < length/4; i++)
{
- chksum += pick_integer_be(buffer, i*4, 4);
+ chksum += get_u32be(&buffer[i*4]);
}
return -chksum;
@@ -464,7 +474,7 @@ static sec_type get_block_type(imgtool::image &img, int block)
if (ret) return ST_INVALID;
/* return type */
- switch ((int32_t) pick_integer_be(buffer, BSIZE-4, 4))
+ switch (get_s32be(&buffer[BSIZE-4]))
{
case 1: return ST_ROOT;
case 2: return ST_USERDIR;
@@ -488,7 +498,7 @@ static imgtoolerr_t read_bitmap_block(imgtool::image &img, int block, bitmap_blo
if (ret) return ret;
/* fill in data */
- bm->chksum = pick_integer_be(buffer, 0, 4);
+ bm->chksum = get_u32be(&buffer[0]);
copy_integer_array_be(bm->map, (uint32_t *) &buffer[4], MSIZE);
return IMGTOOLERR_SUCCESS;
@@ -502,7 +512,7 @@ static imgtoolerr_t write_bitmap_block(imgtool::image &img, int block, const bit
uint8_t buffer[BSIZE];
/* Setup buffer */
- place_integer_be(buffer, 0, 4, bm->chksum);
+ put_u32be(&buffer[0], bm->chksum);
copy_integer_array_be((uint32_t *) &buffer[4], bm->map, MSIZE);
/* write block */
@@ -513,9 +523,8 @@ static imgtoolerr_t write_bitmap_block(imgtool::image &img, int block, const bit
}
-#ifdef UNUSED_FUNCTION
/* Read a bitmap extended block */
-static imgtoolerr_t read_bitmap_ext_block(imgtool::image *img, int block, bitmap_ext_block *bm)
+[[maybe_unused]] static imgtoolerr_t read_bitmap_ext_block(imgtool::image &img, int block, bitmap_ext_block *bm)
{
imgtoolerr_t ret;
uint8_t buffer[BSIZE];
@@ -526,11 +535,10 @@ static imgtoolerr_t read_bitmap_ext_block(imgtool::image *img, int block, bitmap
/* fill in data */
copy_integer_array_be(bm->map, (uint32_t *) &buffer, MSIZE);
- bm->next = pick_integer_be(buffer, BSIZE-4, 4);
+ bm->next = get_u32be(&buffer[BSIZE-4]);
return IMGTOOLERR_SUCCESS;
}
-#endif
/* Read the root block */
@@ -546,17 +554,17 @@ static imgtoolerr_t read_root_block(imgtool::image &img, root_block *root)
/* copy data to root_block */
memset(root, 0, sizeof(root_block));
- root->ht_size = pick_integer_be(buffer, 12, 4);
- root->chksum = pick_integer_be(buffer, 20, 4);
+ root->ht_size = get_u32be(&buffer[12]);
+ root->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(root->ht, (uint32_t *) &buffer[24], TSIZE);
- root->bm_flag = pick_integer_be(buffer, BSIZE-200, 4);
+ root->bm_flag = get_u32be(&buffer[BSIZE-200]);
copy_integer_array_be(root->bm_pages, (uint32_t *) &buffer[BSIZE-196], 25);
copy_date_be(&root->r, (uint32_t *) &buffer[BSIZE-92]);
- root->name_len = pick_integer_be(buffer, BSIZE-80, 1);
+ root->name_len = buffer[BSIZE-80];
memcpy(root->diskname, &buffer[BSIZE-79], 30);
copy_date_be(&root->v, (uint32_t *) &buffer[BSIZE-40]);
copy_date_be(&root->c, (uint32_t *) &buffer[BSIZE-28]);
- root->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ root->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -570,25 +578,25 @@ static imgtoolerr_t write_root_block(imgtool::image &img, const root_block *root
/* Setup buffer */
memset(buffer, 0, BSIZE);
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 12, 4, root->ht_size);
- place_integer_be(buffer, 20, 4, root->chksum);
+ put_u32be(&buffer[0], T_HEADER);
+ put_u32be(&buffer[12], root->ht_size);
+ put_u32be(&buffer[20], root->chksum);
copy_integer_array_be((uint32_t *) &buffer[24], root->ht, TSIZE);
- place_integer_be(buffer, BSIZE-200, 4, root->bm_flag);
+ put_u32be(&buffer[BSIZE-200], root->bm_flag);
copy_integer_array_be((uint32_t *) &buffer[BSIZE-196], root->bm_pages, 25);
- place_integer_be(buffer, BSIZE-92, 4, root->r.days);
- place_integer_be(buffer, BSIZE-88, 4, root->r.mins);
- place_integer_be(buffer, BSIZE-84, 4, root->r.ticks);
- place_integer_be(buffer, BSIZE-80, 1, root->name_len);
+ put_u32be(&buffer[BSIZE-92], root->r.days);
+ put_u32be(&buffer[BSIZE-88], root->r.mins);
+ put_u32be(&buffer[BSIZE-84], root->r.ticks);
+ buffer[BSIZE-80] = root->name_len;
memcpy(&buffer[BSIZE-79], root->diskname, root->name_len);
- place_integer_be(buffer, BSIZE-40, 4, root->v.days);
- place_integer_be(buffer, BSIZE-36, 4, root->v.mins);
- place_integer_be(buffer, BSIZE-32, 4, root->v.ticks);
- place_integer_be(buffer, BSIZE-28, 4, root->c.days);
- place_integer_be(buffer, BSIZE-24, 4, root->c.mins);
- place_integer_be(buffer, BSIZE-20, 4, root->c.ticks);
- place_integer_be(buffer, BSIZE-8, 4, root->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_ROOT);
+ put_u32be(&buffer[BSIZE-40], root->v.days);
+ put_u32be(&buffer[BSIZE-36], root->v.mins);
+ put_u32be(&buffer[BSIZE-32], root->v.ticks);
+ put_u32be(&buffer[BSIZE-28], root->c.days);
+ put_u32be(&buffer[BSIZE-24], root->c.mins);
+ put_u32be(&buffer[BSIZE-20], root->c.ticks);
+ put_u32be(&buffer[BSIZE-8], root->extension);
+ put_u32be(&buffer[BSIZE-4], ST_ROOT);
/* write root block to image */
ret = write_block(img, get_total_blocks(img)/2, buffer);
@@ -609,25 +617,25 @@ static imgtoolerr_t read_file_block(imgtool::image &img, int block, file_block *
if (ret) return ret;
/* fill in data */
- fb->header_key = pick_integer_be(buffer, 4, 4);
- fb->high_seq = pick_integer_be(buffer, 8, 4);
- fb->first_data = pick_integer_be(buffer, 16, 4);
- fb->chksum = pick_integer_be(buffer, 20, 4);
+ fb->header_key = get_u32be(&buffer[4]);
+ fb->high_seq = get_u32be(&buffer[8]);
+ fb->first_data = get_u32be(&buffer[16]);
+ fb->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(fb->data_blocks, (uint32_t *) &buffer[24], TSIZE);
- fb->uid = pick_integer_be(buffer, BSIZE-196, 2);
- fb->gid = pick_integer_be(buffer, BSIZE-194, 2);
- fb->protect = pick_integer_be(buffer, BSIZE-192, 4);
- fb->byte_size = pick_integer_be(buffer, BSIZE-188, 4);
- fb->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ fb->uid = get_u16be(&buffer[BSIZE-196]);
+ fb->gid = get_u16be(&buffer[BSIZE-194]);
+ fb->protect = get_u32be(&buffer[BSIZE-192]);
+ fb->byte_size = get_u32be(&buffer[BSIZE-188]);
+ fb->comm_len = buffer[BSIZE-184];
memcpy(fb->comment, &buffer[BSIZE-183], 79);
copy_date_be(&fb->date, (uint32_t *) &buffer[BSIZE-92]);
- fb->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(fb->filename, (uint32_t *) &buffer[BSIZE-79], 30);
- fb->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- fb->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- fb->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- fb->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fb->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ fb->name_len = buffer[BSIZE-80];
+ memcpy(fb->filename, &buffer[BSIZE-79], 30);
+ fb->real_entry = get_u32be(&buffer[BSIZE-44]);
+ fb->next_link = get_u32be(&buffer[BSIZE-40]);
+ fb->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ fb->parent = get_u32be(&buffer[BSIZE-12]);
+ fb->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -643,12 +651,12 @@ static imgtoolerr_t read_file_ext_block(imgtool::image &img, int block, file_ext
if (ret) return ret;
/* fill in data */
- fe->header_key = pick_integer_be(buffer, 4, 4);
- fe->high_seq = pick_integer_be(buffer, 8, 4);
- fe->chksum = pick_integer_be(buffer, 20, 4);
+ fe->header_key = get_u32be(&buffer[4]);
+ fe->high_seq = get_u32be(&buffer[8]);
+ fe->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(fe->data_blocks, (uint32_t *) &buffer[24], TSIZE);
- fe->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fe->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ fe->parent = get_u32be(&buffer[BSIZE-12]);
+ fe->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -664,11 +672,11 @@ static imgtoolerr_t read_data_block(imgtool::image &img, int block, data_block *
if (ret) return ret;
/* fill in data */
- d->header_key = pick_integer_be(buffer, 4, 4);
- d->seq_num = pick_integer_be(buffer, 8, 4);
- d->data_size = pick_integer_be(buffer, 12, 4);
- d->next_data = pick_integer_be(buffer, 16, 4);
- d->chksum = pick_integer_be(buffer, 20, 4);
+ d->header_key = get_u32be(&buffer[4]);
+ d->seq_num = get_u32be(&buffer[8]);
+ d->data_size = get_u32be(&buffer[12]);
+ d->next_data = get_u32be(&buffer[16]);
+ d->chksum = get_u32be(&buffer[20]);
memcpy(d->data, &buffer[24], BSIZE-24);
return IMGTOOLERR_SUCCESS;
@@ -686,21 +694,21 @@ static imgtoolerr_t read_dir_block(imgtool::image &img, int block, dir_block *db
if (ret) return ret;
/* fill in data */
- db->header_key = pick_integer_be(buffer, 4, 4);
- db->chksum = pick_integer_be(buffer, 20, 4);
+ db->header_key = get_u32be(&buffer[4]);
+ db->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(db->ht, (uint32_t *) &buffer[24], TSIZE);
- db->uid = pick_integer_be(buffer, BSIZE-196, 2);
- db->gid = pick_integer_be(buffer, BSIZE-194, 2);
- db->protect = pick_integer_be(buffer, BSIZE-192, 4);
- db->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ db->uid = get_u16be(&buffer[BSIZE-196]);
+ db->gid = get_u16be(&buffer[BSIZE-194]);
+ db->protect = get_u32be(&buffer[BSIZE-192]);
+ db->comm_len = buffer[BSIZE-184];
memcpy(db->comment, &buffer[BSIZE-183], 79);
copy_date_be(&db->date, (uint32_t *) &buffer[BSIZE-92]);
- db->name_len = pick_integer_be(buffer, BSIZE-80, 1);
+ db->name_len = buffer[BSIZE-80];
memcpy(db->dirname, (uint32_t *) &buffer[BSIZE-79], 30);
- db->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- db->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- db->parent = pick_integer_be(buffer, BSIZE-12, 4);
- db->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ db->next_link = get_u32be(&buffer[BSIZE-40]);
+ db->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ db->parent = get_u32be(&buffer[BSIZE-12]);
+ db->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -714,25 +722,25 @@ static imgtoolerr_t write_dir_block(imgtool::image &img, int block, const dir_bl
memset(buffer, 0, BSIZE);
/* Copy data */
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 4, 4, db->header_key);
- place_integer_be(buffer, 20, 4, db->chksum);
+ put_u32be(&buffer[0], T_HEADER);
+ put_u32be(&buffer[4], db->header_key);
+ put_u32be(&buffer[20], db->chksum);
copy_integer_array_be((uint32_t *) &buffer[24], db->ht, TSIZE);
- place_integer_be(buffer, BSIZE-196, 2, db->uid);
- place_integer_be(buffer, BSIZE-194, 2, db->gid);
- place_integer_be(buffer, BSIZE-192, 4, db->protect);
- place_integer_be(buffer, BSIZE-184, 1, db->comm_len);
- memcpy((uint32_t *) &buffer[BSIZE-183], db->comment, db->comm_len);
- place_integer_be(buffer, BSIZE-92, 4, db->date.days);
- place_integer_be(buffer, BSIZE-88, 4, db->date.mins);
- place_integer_be(buffer, BSIZE-84, 4, db->date.ticks);
- place_integer_be(buffer, BSIZE-80, 1, db->name_len);
- memcpy((uint32_t *) &buffer[BSIZE-79], db->dirname, db->name_len);
- place_integer_be(buffer, BSIZE-40, 4, db->next_link);
- place_integer_be(buffer, BSIZE-16, 4, db->hash_chain);
- place_integer_be(buffer, BSIZE-12, 4, db->parent);
- place_integer_be(buffer, BSIZE-8, 4, db->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_USERDIR);
+ put_u16be(&buffer[BSIZE-196], db->uid);
+ put_u16be(&buffer[BSIZE-194], db->gid);
+ put_u32be(&buffer[BSIZE-192], db->protect);
+ buffer[BSIZE-184] = db->comm_len;
+ memcpy(&buffer[BSIZE-183], db->comment, db->comm_len);
+ put_u32be(&buffer[BSIZE-92], db->date.days);
+ put_u32be(&buffer[BSIZE-88], db->date.mins);
+ put_u32be(&buffer[BSIZE-84], db->date.ticks);
+ buffer[BSIZE-80] = db->name_len;
+ memcpy(&buffer[BSIZE-79], db->dirname, db->name_len);
+ put_u32be(&buffer[BSIZE-40], db->next_link);
+ put_u32be(&buffer[BSIZE-16], db->hash_chain);
+ put_u32be(&buffer[BSIZE-12], db->parent);
+ put_u32be(&buffer[BSIZE-8], db->extension);
+ put_u32be(&buffer[BSIZE-4], ST_USERDIR);
/* Write block to disk */
return write_block(img, block, buffer);
@@ -749,19 +757,19 @@ static imgtoolerr_t read_hardlink_block(imgtool::image &img, int block, hardlink
if (ret) return ret;
/* fill in data */
- hl->header_key = pick_integer_be(buffer, 4, 4);
- hl->chksum = pick_integer_be(buffer, 20, 4);
- hl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- hl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ hl->header_key = get_u32be(&buffer[4]);
+ hl->chksum = get_u32be(&buffer[20]);
+ hl->protect = get_u32be(&buffer[BSIZE-192]);
+ hl->comm_len = buffer[BSIZE-184];
memcpy(hl->comment, &buffer[BSIZE-183], 79);
copy_date_be(&hl->date, (uint32_t *) &buffer[BSIZE-92]);
- hl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(hl->hlname, (uint32_t *) &buffer[BSIZE-79], 30);
- hl->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- hl->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- hl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- hl->parent = pick_integer_be(buffer, BSIZE-12, 4);
- hl->sec_type = pick_integer_be(buffer, BSIZE-4, 4);
+ hl->name_len = buffer[BSIZE-80];
+ memcpy(hl->hlname, &buffer[BSIZE-79], 30);
+ hl->real_entry = get_u32be(&buffer[BSIZE-44]);
+ hl->next_link = get_u32be(&buffer[BSIZE-40]);
+ hl->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ hl->parent = get_u32be(&buffer[BSIZE-12]);
+ hl->sec_type = get_u32be(&buffer[BSIZE-4]);
return IMGTOOLERR_SUCCESS;
}
@@ -777,17 +785,17 @@ static imgtoolerr_t read_softlink_block(imgtool::image &img, int block, softlink
if (ret) return ret;
/* fill in data */
- sl->header_key = pick_integer_be(buffer, 4, 4);
- sl->chksum = pick_integer_be(buffer, 20, 4);
+ sl->header_key = get_u32be(&buffer[4]);
+ sl->chksum = get_u32be(&buffer[20]);
memcpy(sl->symbolic_name, &buffer[24], BSIZE-224);
- sl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- sl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ sl->protect = get_u32be(&buffer[BSIZE-192]);
+ sl->comm_len = buffer[BSIZE-184];
memcpy(sl->comment, &buffer[BSIZE-183], 79);
copy_date_be(&sl->date, (uint32_t *) &buffer[BSIZE-92]);
- sl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(sl->slname, (uint32_t *) &buffer[BSIZE-79], 30);
- sl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- sl->parent = pick_integer_be(buffer, BSIZE-12, 4);
+ sl->name_len = buffer[BSIZE-80];
+ memcpy(sl->slname, &buffer[BSIZE-79], 30);
+ sl->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ sl->parent = get_u32be(&buffer[BSIZE-12]);
return IMGTOOLERR_SUCCESS;
}
@@ -837,16 +845,14 @@ static int is_intl(imgtool::image &img)
t == DT_FFS_INTL_DIRC) ? true : false);
}
-#ifdef UNUSED_FUNCTION
/* Returns true if the disk uses the directory cache mode */
-static int is_dirc(imgtool::image *img)
+[[maybe_unused]] static int is_dirc(imgtool::image &img)
{
disk_type t = get_disk_type(img);
return ((t == DT_OFS_INTL_DIRC ||
t == DT_FFS_INTL_DIRC) ? true : false);
}
-#endif
static imgtoolerr_t get_hash_table(imgtool::image &img, int block, uint32_t *ht)
{
@@ -907,12 +913,10 @@ static imgtoolerr_t set_hash_table(imgtool::image &img, int block, const uint32_
return IMGTOOLERR_SUCCESS;
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t get_root_hash_table(imgtool::image *img, uint32_t *ht)
+[[maybe_unused]] static imgtoolerr_t get_root_hash_table(imgtool::image &img, uint32_t *ht)
{
return get_hash_table(img, get_total_blocks(img)/2, ht);
}
-#endif
static imgtoolerr_t get_blockname(imgtool::image &img, int block, char *dest)
{
@@ -941,7 +945,7 @@ static imgtoolerr_t get_hash_chain(imgtool::image &img, int block, uint32_t *cha
if (ret) return ret;
/* Get chain value */
- *chain = pick_integer_be(buffer, BSIZE-16, 4);
+ *chain = get_u32be(&buffer[BSIZE-16]);
return IMGTOOLERR_SUCCESS;
}
@@ -957,7 +961,7 @@ static imgtoolerr_t set_hash_chain(imgtool::image &img, int block, uint32_t chai
if (ret) return ret;
/* Copy new hash chain value into it */
- place_integer_be(buffer, BSIZE-16, 4, chain);
+ put_u32be(&buffer[BSIZE-16], chain);
/* Write it back again */
ret = write_block(img, block, buffer);
@@ -974,7 +978,7 @@ static imgtoolerr_t walk_hash_chain(imgtool::image &img, const char *path, int s
char name[31];
/* choose compare function depending on intl mode */
- int (*cmp)(const char *, const char *) = is_intl(img) ? &intl_stricmp : &core_stricmp;
+ int (*cmp)(std::string_view, std::string_view) = is_intl(img) ? &intl_stricmp : &core_stricmp;
/* initialize filenames */
memset(name, 0, sizeof(name));
@@ -1174,11 +1178,11 @@ static imgtoolerr_t fix_chksum(imgtool::image &img, int block, int bitmap)
/* update checksum */
if (bitmap)
{
- place_integer_be(buffer, 0, 4, chksum);
+ put_u32be(&buffer[0], chksum);
}
else
{
- place_integer_be(buffer, 20, 4, chksum);
+ put_u32be(&buffer[20], chksum);
}
/* write back new block data */
@@ -1273,9 +1277,9 @@ static imgtoolerr_t update_block_modified_date(imgtool::image &img, int block)
amiga_setup_time(now, &date);
/* Write new time into block */
- place_integer_be(buffer, BSIZE-92, 4, date.days);
- place_integer_be(buffer, BSIZE-88, 4, date.mins);
- place_integer_be(buffer, BSIZE-84, 4, date.ticks);
+ put_u32be(&buffer[BSIZE-92], date.days);
+ put_u32be(&buffer[BSIZE-88], date.mins);
+ put_u32be(&buffer[BSIZE-84], date.ticks);
/* Write block back to disk */
ret = write_block(img, block, buffer);
@@ -1367,8 +1371,7 @@ static int get_first_bit(uint32_t *array, int size)
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image *img, int start, int *block)
+[[maybe_unused]] static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image &img, int start, int *block)
{
imgtoolerr_t ret;
bitmap_ext_block bm_ext;
@@ -1400,7 +1403,6 @@ static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image *img, int start, int *
/* else continue walking the list */
return walk_bitmap_ext_blocks(img, bm_ext.next, block);
}
-#endif
/* Searches for a block marked as free
@@ -1710,7 +1712,7 @@ static imgtoolerr_t write_file_ext_data(imgtool::image &img, int block, int *fil
static imgtoolerr_t clear_file_ext_data(imgtool::image &img, int block, int *filesize)
{
- return walk_file_ext_data(img, block, filesize, NULL, false);
+ return walk_file_ext_data(img, block, filesize, nullptr, false);
}
@@ -1979,6 +1981,7 @@ static imgtoolerr_t amiga_image_nextenum(imgtool::directory &enumeration, imgtoo
case ST_LINKDIR:
ent.directory = 1;
+ [[fallthrough]];
case ST_LINKFILE:
{
@@ -2337,7 +2340,7 @@ static imgtoolerr_t amiga_image_geticoninfo(imgtool::partition &partition, const
}
-static imgtoolerr_t amiga_image_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t amiga_image_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
return IMGTOOLERR_UNIMPLEMENTED;
}
@@ -2384,7 +2387,7 @@ void amiga_floppy_get_info(const imgtool_class *imgclass, uint32_t state, union
case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "amiga_floppy"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Amiga floppy disk image (OFS/FFS format)"); break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "adf"); break;
diff --git a/src/tools/imgtool/modules/bml3.cpp b/src/tools/imgtool/modules/bml3.cpp
index a1a3bdc203d..8c465032f28 100644
--- a/src/tools/imgtool/modules/bml3.cpp
+++ b/src/tools/imgtool/modules/bml3.cpp
@@ -18,12 +18,18 @@
- (used with MP-1802 floppy disk controller card)
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "imgtool.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
#define MAX_SECTOR_SIZE 256
struct bml3_diskinfo
@@ -129,7 +135,7 @@ static floperr_t get_bml3_dirent(imgtool::image &f, int index_loc, struct bml3_d
ent->ftype = buf[11];
ent->asciiflag = buf[12];
ent->first_granule = buf[13];
- ent->lastsectorbytes = (buf[14] << 8) | buf[15];
+ ent->lastsectorbytes = get_u16be(&buf[14]);
break;
default:
return FLOPPY_ERROR_INVALIDIMAGE;
@@ -162,8 +168,7 @@ static floperr_t put_bml3_dirent(imgtool::image &f, int index_loc, const struct
buf[11] = ent->ftype;
buf[12] = ent->asciiflag;
buf[13] = ent->first_granule;
- buf[14] = ent->lastsectorbytes >> 8;
- buf[15] = ent->lastsectorbytes & 0xff;
+ put_u16be(&buf[14], ent->lastsectorbytes);
break;
default:
return FLOPPY_ERROR_INVALIDIMAGE;
@@ -512,7 +517,10 @@ static imgtoolerr_t bml3_diskimage_open(imgtool::image &image, imgtool::stream::
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);
+
+ int sectors_per_track = -1;
+ if (callbacks->get_sectors_per_track)
+ 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
@@ -604,8 +612,8 @@ eof:
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'));
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname);
+ snprintf(ent.attr, std::size(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
}
return IMGTOOLERR_SUCCESS;
}
@@ -832,7 +840,7 @@ static imgtoolerr_t bml3_diskimage_deletefile(imgtool::partition &partition, con
-static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t err;
imgtool::image &image(partition.image());
@@ -848,27 +856,27 @@ static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition
if (ent.asciiflag == 0xFF)
{
/* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
}
else if (ent.ftype == 0)
{
/* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_bml3bas_getinfo;
}
}
else
{
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_bml3bas_getinfo;
}
@@ -903,9 +911,9 @@ void bml3_get_info(const imgtool_class *imgclass, uint32_t state, union imgtooli
/* --- the following bits of info are returned as 64-bit signed integers --- */
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(bml3_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct bml3_direnum); break;
+ case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct bml3_direnum); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "bml3"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Basic Master Level 3 format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
diff --git a/src/tools/imgtool/modules/concept.cpp b/src/tools/imgtool/modules/concept.cpp
index 6bc0fe1bf22..da9689d455a 100644
--- a/src/tools/imgtool/modules/concept.cpp
+++ b/src/tools/imgtool/modules/concept.cpp
@@ -8,12 +8,15 @@
Raphael Nabet, 2003
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
#include "imgtool.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
struct UINT16xE
{
uint8_t bytes[2];
@@ -201,7 +204,6 @@ static int read_physical_record(imgtool::stream &file_handle, int secnum, void *
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
write_physical_record
@@ -213,7 +215,7 @@ static int read_physical_record(imgtool::stream &file_handle, int secnum, void *
Return non-zero on error
*/
-static int write_physical_record(imgtool::stream *file_handle, int secnum, const void *src)
+[[maybe_unused]] static int write_physical_record(imgtool::stream *file_handle, int secnum, const void *src)
{
int reply;
@@ -228,7 +230,6 @@ static int write_physical_record(imgtool::stream *file_handle, int secnum, const
return 0;
}
-#endif
/*
Search for a file name on a concept_image
@@ -357,8 +358,8 @@ static imgtoolerr_t concept_image_nextenum(imgtool::directory &enumeration, imgt
int len = iter->image->dev_dir.file_dir[iter->index].filename[0];
const char *type;
- if (len > ARRAY_LENGTH(ent.filename))
- len = ARRAY_LENGTH(ent.filename);
+ if (len > std::size(ent.filename))
+ len = std::size(ent.filename);
memcpy(ent.filename, iter->image->dev_dir.file_dir[iter->index].filename + 1, len);
ent.filename[len] = 0;
@@ -382,7 +383,7 @@ static imgtoolerr_t concept_image_nextenum(imgtool::directory &enumeration, imgt
type = "???";
break;
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%s", type);
+ snprintf(ent.attr, std::size(ent.attr), "%s", type);
/* len in physrecs */
ent.filesize = get_UINT16xE(iter->image->dev_dir.vol_hdr.disk_flipped, iter->image->dev_dir.file_dir[iter->index].next_block)
diff --git a/src/tools/imgtool/modules/cybiko.cpp b/src/tools/imgtool/modules/cybiko.cpp
index 1b9f43ee298..bfe9bfdddb2 100644
--- a/src/tools/imgtool/modules/cybiko.cpp
+++ b/src/tools/imgtool/modules/cybiko.cpp
@@ -10,6 +10,9 @@
#include "imgtool.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
#include <zlib.h>
struct cybiko_file_system
@@ -52,8 +55,8 @@ enum
};
#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
+#define BLOCK_FILE_ID(x) get_u16be( x + 2)
+#define BLOCK_PART_ID(x) get_u16be( x + 4)
#define BLOCK_FILENAME(x) (char*)(x + 7)
#define FILE_HEADER_SIZE 0x48
@@ -79,30 +82,6 @@ uint32_t cybiko_time_setup(const imgtool::datetime &t)
return cybiko_time_point.time_since_epoch().count();
}
-static uint32_t buffer_read_32_be( uint8_t *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static uint16_t buffer_read_16_be( uint8_t *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( uint8_t *buffer, uint32_t data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( uint8_t *buffer, uint16_t data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
// page = crc1 (4) + wcnt (2) + crc2 (2) + data (x) + unk (2)
static uint32_t page_buffer_calc_checksum_1( uint8_t *buffer, uint32_t size, int block_type)
@@ -113,9 +92,9 @@ static uint32_t page_buffer_calc_checksum_1( uint8_t *buffer, uint32_t size, int
static uint16_t page_buffer_calc_checksum_2( uint8_t *buffer)
{
uint16_t val = 0xAF17;
- val ^= buffer_read_16_be( buffer + 0);
- val ^= buffer_read_16_be( buffer + 2);
- val ^= buffer_read_16_be( buffer + 4);
+ val ^= get_u16be( buffer + 0);
+ val ^= get_u16be( buffer + 2);
+ val ^= get_u16be( buffer + 4);
return swapendian_int16(val);
}
@@ -124,11 +103,11 @@ static int page_buffer_verify( uint8_t *buffer, uint32_t size, int block_type)
uint32_t checksum_page, checksum_calc;
// checksum 1
checksum_calc = page_buffer_calc_checksum_1( buffer, size, block_type);
- checksum_page = buffer_read_32_be( buffer + 0);
+ checksum_page = get_u32be( buffer + 0);
if (checksum_calc != checksum_page) return false;
// checksum 2
checksum_calc = page_buffer_calc_checksum_2( buffer);
- checksum_page = buffer_read_16_be( buffer + 6);
+ checksum_page = get_u16be( buffer + 6);
if (checksum_calc != checksum_page) return false;
// ok
return true;
@@ -198,10 +177,10 @@ static int cfs_block_write( cybiko_file_system *cfs, uint8_t *buffer, int block_
uint8_t buffer_page[MAX_PAGE_SIZE];
uint32_t page;
memcpy( buffer_page + 8, buffer, cfs->page_size - 10);
- buffer_write_32_be( buffer_page + 0, page_buffer_calc_checksum_1( buffer_page, cfs->page_size, block_type));
- buffer_write_16_be( buffer_page + 4, cfs->write_count++);
- buffer_write_16_be( buffer_page + 6, page_buffer_calc_checksum_2( buffer_page));
- buffer_write_16_be( buffer_page + cfs->page_size - 2, 0xFFFF);
+ put_u32be( buffer_page + 0, page_buffer_calc_checksum_1( buffer_page, cfs->page_size, block_type));
+ put_u16be( buffer_page + 4, cfs->write_count++);
+ put_u16be( buffer_page + 6, page_buffer_calc_checksum_2( buffer_page));
+ put_u16be( buffer_page + cfs->page_size - 2, 0xFFFF);
if (!cfs_block_to_page( cfs, block_type, block, &page)) return false;
if (!cfs_page_write( cfs, buffer_page, page)) return false;
return true;
@@ -236,7 +215,7 @@ static int cfs_file_info( cybiko_file_system *cfs, uint16_t file_id, cfs_file *f
if (BLOCK_PART_ID(buffer) == 0)
{
strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
+ file->date = get_u32be( buffer + 6 + FILE_HEADER_SIZE - 4);
}
file->size += buffer[1];
file->blocks++;
@@ -499,13 +478,13 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
buffer[0] = 0x80;
buffer[1] = cfs->page_size - 0x10 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
+ put_u16be( buffer + 2, file_id);
+ put_u16be( buffer + 4, part_id);
if (part_id == 0)
{
buffer[6] = 0;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be(buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
+ put_u32be(buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/cybikoxt.cpp b/src/tools/imgtool/modules/cybikoxt.cpp
index 8c2980de449..556f37fde76 100644
--- a/src/tools/imgtool/modules/cybikoxt.cpp
+++ b/src/tools/imgtool/modules/cybikoxt.cpp
@@ -10,6 +10,8 @@
#include "imgtool.h"
+#include "multibyte.h"
+
#include <zlib.h>
struct cybiko_file_system
@@ -44,8 +46,8 @@ enum
#define INVALID_FILE_ID 0xFFFF
#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
+#define BLOCK_FILE_ID(x) get_u16be( x + 2)
+#define BLOCK_PART_ID(x) get_u16be( x + 4)
#define BLOCK_FILENAME(x) (char*)(x + 7)
#define FILE_HEADER_SIZE 0x48
@@ -58,30 +60,6 @@ static cybiko_file_system *get_cfs(imgtool::image &image)
extern imgtool::datetime cybiko_time_crack(uint32_t cfs_time);
extern uint32_t cybiko_time_setup(const imgtool::datetime &t);
-static uint32_t buffer_read_32_be( uint8_t *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static uint16_t buffer_read_16_be( uint8_t *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( uint8_t *buffer, uint32_t data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( uint8_t *buffer, uint16_t data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
// page = crc (2) + data (x)
static uint16_t page_buffer_calc_checksum( uint8_t *data, uint32_t size)
@@ -103,7 +81,7 @@ static int page_buffer_verify( uint8_t *buffer, uint32_t size, int block_type)
{
uint32_t checksum_page, checksum_calc;
checksum_calc = page_buffer_calc_checksum( buffer + 2, size - 2);
- checksum_page = buffer_read_16_be( buffer + 0);
+ checksum_page = get_u16be( buffer + 0);
if (checksum_calc != checksum_page) return false;
}
// ok
@@ -183,7 +161,7 @@ static int cfs_block_write( cybiko_file_system *cfs, uint8_t *buffer, int block_
{
checksum = page_buffer_calc_checksum( buffer_page + 2, cfs->page_size - 2);
}
- buffer_write_16_be( buffer_page + 0, checksum);
+ put_u16be( buffer_page + 0, checksum);
if (!cfs_block_to_page( cfs, block_type, block, &page)) return false;
if (!cfs_page_write( cfs, buffer_page, page)) return false;
return true;
@@ -218,7 +196,7 @@ static int cfs_file_info( cybiko_file_system *cfs, uint16_t file_id, cfs_file *f
if (BLOCK_PART_ID(buffer) == 0)
{
strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
+ file->date = get_u32be( buffer + 6 + FILE_HEADER_SIZE - 4);
}
file->size += buffer[1];
file->blocks++;
@@ -460,13 +438,13 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
buffer[0] = 0x80;
buffer[1] = (cfs->page_size - 2) - 6 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
+ put_u16be( buffer + 2, file_id);
+ put_u16be( buffer + 4, part_id);
if (part_id == 0)
{
buffer[6] = 0x20;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
+ put_u32be( buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/dgndos.cpp b/src/tools/imgtool/modules/dgndos.cpp
new file mode 100644
index 00000000000..692c010d057
--- /dev/null
+++ b/src/tools/imgtool/modules/dgndos.cpp
@@ -0,0 +1,1256 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/****************************************************************************
+
+ dgndos.cpp
+
+ Dragon DOS disk images
+
+ I am not happy with the sector allocation algorithm
+
+****************************************************************************/
+
+#include "imgtool.h"
+#include "filter.h"
+#include "iflopimg.h"
+
+#include "formats/coco_dsk.h"
+#include "corestr.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#ifdef _MSC_VER
+#pragma pack(push,1)
+#define A_PACKED
+#else
+#define A_PACKED __attribute__((packed))
+#endif
+
+typedef struct A_PACKED dngdos_sector_allocation_format {
+ uint16_t lsn;
+ uint8_t count;
+} dngdos_sector_allocation_format;
+
+typedef struct A_PACKED dngdos_file_header_block {
+ char filename[11];
+ dngdos_sector_allocation_format block[4];
+} dngdos_file_header_block;
+
+typedef struct A_PACKED dngdos_file_continuation_block {
+ dngdos_sector_allocation_format block[7];
+ uint16_t unused;
+} dngdos_file_continuation_block;
+
+struct A_PACKED dgndos_dirent
+{
+ unsigned char flag_byte;
+ union block {
+ dngdos_file_header_block header;
+ dngdos_file_continuation_block continuation;
+ } block;
+ uint8_t dngdos_last_or_next;
+};
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+struct dgndos_direnum
+{
+ int index;
+ bool eof;
+};
+
+/*********************************************************************
+ Imgtool module code
+*********************************************************************/
+
+#define DGNDOS_OPTIONS_PROTECT 'P'
+#define MAX_DIRENTS 160
+#define HEADER_EXTENTS_COUNT 4
+#define CONT_EXTENTS_COUNT 7
+
+#define DGNDOS_DELETED_BIT 0x80 // deleted entry
+#define DGNDOS_CONTINUED_BIT 0x20 // byte at offset 0x18 give next entry number
+#define DGNDOS_END_BIT 0x08 // end of directory
+#define DGNDOS_PROTECT_BIT 0x02 // ignored
+#define DGNDOS_CONTINUATION_BIT 0x01 // this is a continuation block
+
+static imgtoolerr_t get_dgndos_dirent(uint8_t *track, int index_loc, dgndos_dirent &ent)
+{
+ if (index_loc >= MAX_DIRENTS)
+ return IMGTOOLERR_FILENOTFOUND;
+
+ int sector = 3 + (index_loc / 10);
+ int offset = (index_loc * 25) % 250;
+
+ memcpy( (void *)&ent, track + (256 * (sector-1)) + offset, sizeof(ent));
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t put_dgndos_dirent(uint8_t *track, int index_loc, const dgndos_dirent &ent)
+{
+ if (index_loc >= MAX_DIRENTS)
+ return IMGTOOLERR_FILENOTFOUND;
+
+ int sector = 3 + (index_loc / 10);
+ int offset = (index_loc * 25) % 250;
+
+ memcpy( track + (256 * (sector-1)) + offset, (void *)&ent, sizeof(ent));
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static std::string get_dirent_fname(const dgndos_dirent &ent)
+{
+ return extract_padded_filename(ent.block.header.filename, 8, 3, '\0');
+}
+
+static bool dgndos_real_file( dgndos_dirent &ent )
+{
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) return false;
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT) return false;
+
+ return true;
+}
+
+static imgtoolerr_t lookup_dgndos_file(uint8_t *entire_track, const char *fname, dgndos_dirent &ent, int *position = nullptr)
+{
+ int i = 0;
+ imgtoolerr_t err;
+ std::string fnamebuf;
+
+ do
+ {
+ do
+ {
+ err = get_dgndos_dirent( entire_track, i++, ent );
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_END_BIT ) return IMGTOOLERR_FILENOTFOUND;
+ }
+ while( ! dgndos_real_file(ent) );
+
+ fnamebuf = get_dirent_fname(ent);
+ }
+ while(core_stricmp(fnamebuf, fname));
+
+ if (position)
+ *position = i - 1;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_geometry(uint8_t *entire_track, int *bitmap_count, int *heads, int *tracks_on_disk, int *sectors_per_track)
+{
+ unsigned int tod, spt, sides;
+
+ tod = entire_track[0xfc];
+ spt = entire_track[0xfd];
+
+ if( (~tod & 0xff) != entire_track[0xfe])
+ {
+// fprintf( stderr, "tracks_on_disk check failed: %u == %u\n", (~tod & 0xff), entire_track[0xfe] );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if( (~spt & 0xff) != entire_track[0xff])
+ {
+// fprintf( stderr, "sectors_per_track check failed: %u == %u\n", (~spt & 0xff), entire_track[0xff] );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if(spt == 36)
+ {
+ sides = 1;
+ }
+ else if(spt == 18 )
+ {
+ sides = 0;
+ }
+ else
+ {
+// fprintf( stderr, "sides check failed\n" );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if( heads ) *heads = sides;
+ if( tracks_on_disk) *tracks_on_disk = tod;
+ if( sectors_per_track ) *sectors_per_track = spt;
+ if( bitmap_count ) *bitmap_count = (tod * sides * 18) + (tod * 18);
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_convert_lsn(uint8_t *entire_track, int lsn, int *head, int *track, int *sector )
+{
+ int tracks_on_disk;
+ int sectors_per_track;
+ int sides;
+
+ imgtoolerr_t err = dgndos_get_geometry(entire_track, nullptr, &sides, &tracks_on_disk, &sectors_per_track);
+ if(err) return err;
+
+ if( sides == 0 )
+ {
+ *head = 0;
+ *track = lsn / 18;
+ *sector = (lsn % 18) + 1;
+ }
+ else
+ {
+ *head = (lsn / 18) % 2;
+ *track = lsn / 36;
+ *sector = (lsn % 18) + 1;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+#define ALLOCATE_BIT 1
+#define QUERY_BIT 0
+#define DEALLOCATE_BIT -1
+
+static int dgndos_set_reset_bitmap( uint8_t *entire_track, int lsn, int set )
+{
+ int startbyte = lsn / 8;
+ int startbit = lsn % 8;
+
+ if( lsn > 1439 ) startbyte += 76;
+
+ if(set > QUERY_BIT) // ALLOCATE_BIT
+ {
+ // 0 = used, 1 = free
+ entire_track[startbyte] &= ~(1 << startbit);
+ }
+ else if( set < QUERY_BIT ) // DEALLOCATE_BIT
+ {
+ // 0 = used, 1 = free
+ entire_track[startbyte] |= (1 << startbit);
+ }
+
+ // 0 = used, 1 = free
+ return (entire_track[startbyte] & (1 << startbit)) != 0;
+}
+
+static int dgndos_is_sector_avaiable(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, QUERY_BIT );
+}
+
+static int dgndos_fat_allocate_sector(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, ALLOCATE_BIT );
+}
+
+static int dgndos_fat_deallocate_sector(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, DEALLOCATE_BIT );
+}
+
+static int dgndos_fat_deallocate_span(uint8_t *entire_track, int lsn, int count)
+{
+ int value = 0;
+
+ for( int i=lsn; i<lsn+count; i++)
+ {
+ value = dgndos_fat_deallocate_sector(entire_track, i);
+ }
+
+ return value;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_dirent_position(uint8_t *entire_track, int *position )
+{
+ int i;
+ imgtoolerr_t err;
+ dgndos_dirent ent;
+
+ for( i=0; i<MAX_DIRENTS; i++ )
+ {
+ err = get_dgndos_dirent(entire_track, i, ent);
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) break;
+
+ if( ent.flag_byte & DGNDOS_END_BIT) break;
+ }
+
+ if( i == MAX_DIRENTS )
+ {
+ return IMGTOOLERR_NOSPACE;
+ }
+
+ if( position ) *position = i;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_dirent(uint8_t *entire_track, dgndos_dirent &ent, int *position )
+{
+ int i;
+ imgtoolerr_t err;
+
+ for( i=0; i<MAX_DIRENTS; i++ )
+ {
+ err = get_dgndos_dirent(entire_track, i, ent);
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) break;
+
+ if( ent.flag_byte & DGNDOS_END_BIT) break;
+ }
+
+ if( i == MAX_DIRENTS )
+ {
+ return IMGTOOLERR_NOSPACE;
+ }
+
+ if( position ) *position = i;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_sector( uint8_t *entire_track, int *lsn )
+{
+ int bitmap_count, i;
+ int pos_diff = 18;
+ int neg_diff = 36;
+ int start = 360;
+
+ imgtoolerr_t err = dgndos_get_geometry(entire_track, &bitmap_count, nullptr, nullptr, nullptr);
+ if(err) return err;
+
+ do
+ {
+ i = start;
+ while ( i >= 0 )
+ {
+ if( dgndos_is_sector_avaiable(entire_track, i) )
+ {
+ *lsn = i;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ i -= neg_diff;
+ }
+
+ i = start;
+ while( i < bitmap_count )
+ {
+ if( dgndos_is_sector_avaiable(entire_track, i) )
+ {
+ *lsn = i;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ i += pos_diff;
+ }
+
+ start--;
+ }
+ while( start >= 335 );
+
+ return IMGTOOLERR_NOSPACE;
+}
+
+static imgtoolerr_t dgndos_count_dirents(uint8_t *entire_track, dgndos_dirent dgnent, int *result)
+{
+ imgtoolerr_t err = IMGTOOLERR_SUCCESS;
+ *result = 1;
+
+ while( (dgnent.flag_byte & DGNDOS_CONTINUED_BIT) && *result < MAX_DIRENTS )
+ {
+ (*result)++;
+ err = get_dgndos_dirent(entire_track, dgnent.dngdos_last_or_next, dgnent);
+ }
+
+ return err;
+}
+
+static imgtoolerr_t dgndos_get_file_size(uint8_t *entire_track, dgndos_dirent dgnent, size_t &filesize)
+{
+ imgtoolerr_t err;
+ int directory_entry_count = 0;
+ int extent = 0;
+ int block_size;
+ int done;
+ int count;
+ int i;
+
+ filesize = 0;
+
+ do
+ {
+ if(directory_entry_count>MAX_DIRENTS) return IMGTOOLERR_CORRUPTDIR;
+
+ count = dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? dgnent.block.continuation.block[extent].count : dgnent.block.header.block[extent].count;
+
+ if( count == 0 ) break;
+
+ i = 0;
+
+ // count extents except last sector
+ while (i < count - 1)
+ {
+ filesize += 256;
+ i++;
+ }
+
+ block_size = 256;
+ done = false;
+
+ if( extent < (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1 )
+ {
+ if( (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? dgnent.block.continuation.block[extent+1].count : dgnent.block.header.block[extent+1].count) == 0 )
+ {
+ // not last extent, and yes continuation
+ if( dgnent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = dgnent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+ else if( extent == (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1)
+ {
+ if( !(dgnent.flag_byte & DGNDOS_CONTINUED_BIT) )
+ {
+ // is last extent, and no continuation
+ if( dgnent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = dgnent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+
+ filesize += block_size;
+
+ extent++;
+
+ if( extent == (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) )
+ {
+ if( dgnent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ err = get_dgndos_dirent(entire_track, dgnent.dngdos_last_or_next, *(&dgnent) );
+ if(err) return err;
+
+ extent = 0;
+ directory_entry_count++;
+ }
+ }
+ }
+ while( !done );
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static floperr_t dgndos_get_directory_track( imgtool::image &image, int track, uint8_t *buffer )
+{
+ floperr_t ferr;
+
+ for(int i=1; i<=18; i++ )
+ {
+ ferr = floppy_read_sector(imgtool_floppy(image), 0, track, i, 0, &(buffer[(i-1)*256]), 256);
+ if(ferr) break;
+ }
+
+ return ferr;
+}
+
+static floperr_t dgndos_put_directory_track( imgtool::image &image, int track, uint8_t *buffer )
+{
+ floperr_t ferr;
+
+ for(int i=1; i<=18; i++ )
+ {
+ ferr = floppy_write_sector(imgtool_floppy(image), 0, track, i, 0, &(buffer[(i-1)*256]), 256, 0);
+ if(ferr) break;
+ }
+
+ return ferr;
+}
+
+static imgtoolerr_t dgndos_diskimage_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ size_t filesize;
+ dgndos_direnum *dgnenum;
+ dgndos_dirent dgnent;
+ int dir_ent_count;
+
+ imgtool::image &image(enumeration.image());
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ dgnenum = (dgndos_direnum *) enumeration.extra_bytes();
+
+ /* Did we hit the end of file before? */
+ if (dgnenum->eof) return IMGTOOLERR_SUCCESS;
+
+ do
+ {
+ if (dgnenum->index >= MAX_DIRENTS)
+ {
+ dgnenum->eof = 1;
+ ent.eof = 1;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ err = get_dgndos_dirent(entire_track20, dgnenum->index++, dgnent);
+ if (err) return err;
+
+ if( dgndos_real_file( dgnent ) ) break;
+ }
+ while( ! (dgnent.flag_byte & DGNDOS_END_BIT) );
+
+ // now are we at the eof point?
+ if (dgnent.flag_byte & DGNDOS_END_BIT)
+ {
+ dgnenum->eof = 1;
+ ent.eof = 1;
+ }
+ else
+ {
+ err = dgndos_get_file_size(entire_track20, dgnent, 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(dgnent);
+
+ err = dgndos_count_dirents(entire_track20, dgnent, &dir_ent_count);
+ if (err) return err;
+
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname.c_str());
+ snprintf(ent.attr, std::size(ent.attr), "%c (%03d)",
+ (char) (dgnent.flag_byte & DGNDOS_PROTECT_BIT ? 'P' : '.'),
+ dir_ent_count);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_freespace(imgtool::partition &partition, uint64_t *size)
+{
+ floperr_t ferr;
+ imgtool::image &image(partition.image());
+ int bitmap_count(0);
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ *size = 0;
+
+ dgndos_get_geometry(entire_track20, &bitmap_count, nullptr, nullptr, nullptr);
+
+ for( int i=0; i<bitmap_count; i++ )
+ {
+ if (dgndos_is_sector_avaiable(entire_track20, i))
+ {
+ *size += 256;
+ }
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_readfile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &destf)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ dgndos_dirent ent;
+ imgtool::image &image(partition.image());
+ int directory_entry_count = 0;
+ int head, track, sector;
+ int position;
+ int extent = 0;
+ int block_size;
+ int done;
+ int lsn;
+ int count;
+ int i;
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ err = lookup_dgndos_file(entire_track20, fname, ent, &position);
+ if (err) return err;
+
+ do
+ {
+ if(directory_entry_count>MAX_DIRENTS) return IMGTOOLERR_CORRUPTDIR;
+
+ lsn = big_endianize_int16( ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent].lsn : ent.block.header.block[extent].lsn );
+ count = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent].count : ent.block.header.block[extent].count;
+
+ if( count == 0 ) break;
+
+ i = 0;
+
+ // get extents except last sector
+ while (i < count - 1)
+ {
+ err = dgndos_convert_lsn(entire_track20, lsn + i, &head, &track, &sector );
+ if(err) return err;
+
+ err = imgtool_floppy_read_sector_to_stream(image, head, track, sector, 0, 256, destf);
+ if (err) return err;
+
+ i++;
+ }
+
+ block_size = 256;
+ done = false;
+
+ if( extent < (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1 )
+ {
+ if( (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent+1].count : ent.block.header.block[extent+1].count) == 0 )
+ {
+ // not last extent, and yes continuation
+ if( ent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = ent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+ else if( extent == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1)
+ {
+ if( !(ent.flag_byte & DGNDOS_CONTINUED_BIT) )
+ {
+ // is last extent, and no continuation
+ if( ent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = ent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+
+ err = dgndos_convert_lsn(entire_track20, lsn + i, &head, &track, &sector );
+ if(err) return err;
+
+ err = imgtool_floppy_read_sector_to_stream(image, head, track, sector, 0, block_size, destf);
+ if (err) return err;
+
+ extent++;
+
+ if( extent == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) )
+ {
+ if( ent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ position = ent.dngdos_last_or_next;
+ err = get_dgndos_dirent(entire_track20, ent.dngdos_last_or_next, ent );
+ if(err) return err;
+
+ extent = 0;
+ directory_entry_count++;
+ }
+ }
+ }
+ while( !done );
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_deletefile(imgtool::partition &partition, const char *fname)
+{
+ imgtoolerr_t err;
+ floperr_t ferr;
+ imgtool::image &image(partition.image());
+ int pos;
+ struct dgndos_dirent ent;
+ int directory_entry_count = 0;
+
+ uint8_t entire_track20[18*256];
+ uint8_t entire_track16[18*256];
+ bool write_20_to_16;
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ ferr = dgndos_get_directory_track( image, 16, entire_track16 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ write_20_to_16 = memcmp(entire_track20, entire_track16, 256*18 );
+
+ err = lookup_dgndos_file(entire_track20, fname, ent, &pos);
+ if (err) return err;
+
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ ent.flag_byte &= ~DGNDOS_PROTECT_BIT;
+
+ for( int i=0; i<HEADER_EXTENTS_COUNT; i++)
+ {
+ if( ent.block.header.block[i].count != 0)
+ {
+ dgndos_fat_deallocate_span(entire_track20, big_endianize_int16(ent.block.header.block[i].lsn), ent.block.header.block[i].count);
+
+ ent.block.header.block[i].lsn = 0;
+ ent.block.header.block[i].count = 0;
+ }
+ else break;
+ }
+
+ int continue_flag = ent.flag_byte & DGNDOS_CONTINUED_BIT;
+ int continue_dirent_index = ent.dngdos_last_or_next;
+
+ ent.dngdos_last_or_next = 0;
+ err = put_dgndos_dirent(entire_track20, pos, ent);
+ if (err) return err;
+
+ while( continue_flag )
+ {
+ if( directory_entry_count > MAX_DIRENTS ) return IMGTOOLERR_CORRUPTDIR;
+
+ int dirent_index = continue_dirent_index;
+ err = get_dgndos_dirent(entire_track20, dirent_index, ent);
+ if (err) return err;
+
+ for( int i=0; i<CONT_EXTENTS_COUNT; i++)
+ {
+ if(ent.block.continuation.block[i].count !=0)
+ {
+ dgndos_fat_deallocate_span(entire_track20, big_endianize_int16(ent.block.continuation.block[i].lsn), ent.block.continuation.block[i].count);
+
+ ent.block.continuation.block[i].lsn = 0;
+ ent.block.continuation.block[i].count = 0;
+ }
+ else break;
+ }
+
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ continue_flag = ent.flag_byte & DGNDOS_CONTINUED_BIT;
+ continue_dirent_index = ent.dngdos_last_or_next;
+
+ ent.dngdos_last_or_next = 0;
+ err = put_dgndos_dirent(entire_track20, dirent_index, ent);
+ if (err) return err;
+
+ directory_entry_count++;
+ }
+
+ ferr = dgndos_put_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if( write_20_to_16 )
+ {
+ ferr = dgndos_put_directory_track( image, 16, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_prepare_dirent(uint8_t *track, dgndos_dirent &ent, const char *fname)
+{
+ const char *fname_end;
+ const char *fname_ext;
+ int fname_ext_len;
+
+ memset(&ent, '\0', sizeof(ent));
+
+ fname_end = strchr(fname, '.');
+ if (fname_end)
+ fname_ext = fname_end + 1;
+ else
+ fname_end = fname_ext = fname + strlen(fname);
+
+ fname_ext_len = strlen(fname_ext);
+
+ // we had better be an 8.3 filename
+ if (((fname_end - fname) > 8) || (fname_ext_len > 3))
+ return IMGTOOLERR_BADFILENAME;
+
+ memcpy(&ent.block.header.filename[0], fname, fname_end - fname);
+ memcpy(&ent.block.header.filename[8], fname_ext, fname_ext_len);
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_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 &image(partition.image());
+ dgndos_dirent ent;
+ int position;
+ uint64_t written = 0;
+ int fat_block, first_lsn, sectors_avaiable, current_sector_index;
+ int last_sector_size = 0;
+ int bitmap_count;
+
+ if( sourcef.size() == 0 ) return IMGTOOLERR_BUFFERTOOSMALL;
+
+ uint8_t entire_track20[18*256];
+ uint8_t entire_track16[18*256];
+ bool write_20_to_16;
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ ferr = dgndos_get_directory_track( image, 16, entire_track16 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ write_20_to_16 = memcmp(entire_track20, entire_track16, 18*256 );
+
+ err = dgndos_get_geometry(entire_track20, &bitmap_count, nullptr, nullptr, nullptr);
+ if(err) return err;
+
+ // find directory entry with same file name
+ err = lookup_dgndos_file(entire_track20, fname, ent, &position);
+
+ if( err == IMGTOOLERR_FILENOTFOUND )
+ {
+ int new_lsn;
+
+ // get new directory entry
+ err = dgndos_get_avaiable_dirent(entire_track20, ent, &position);
+ if (err) return err;
+
+ err = dgndos_prepare_dirent(entire_track20, ent, fname);
+ if(err) return err;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err)
+ {
+ return err;
+ }
+
+ dgndos_fat_allocate_sector(entire_track20, new_lsn);
+
+ ent.block.header.block[0].lsn = big_endianize_int16(new_lsn);
+ ent.block.header.block[0].count = 1;
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if(err) return err;
+ }
+ else if(err != IMGTOOLERR_SUCCESS )
+ {
+ return err;
+ }
+
+ if( writeoptions->lookup_int(DGNDOS_OPTIONS_PROTECT))
+ {
+ ent.flag_byte |= DGNDOS_PROTECT_BIT;
+ }
+ else
+ {
+ ent.flag_byte &= ~DGNDOS_PROTECT_BIT;
+ }
+
+ fat_block = 0;
+
+ /* get next available fat entry */
+ first_lsn = big_endianize_int16(ent.block.header.block[fat_block].lsn);
+ sectors_avaiable = ent.block.header.block[fat_block].count;
+ current_sector_index = 0;
+
+ do
+ {
+ while ((current_sector_index < sectors_avaiable) && (written < sourcef.size()))
+ {
+ int head, track, sector, write_count;
+
+ err = dgndos_convert_lsn(entire_track20, first_lsn + current_sector_index, &head, &track, &sector );
+ if (err) return err;
+
+ if( sourcef.size() - written > 256 )
+ {
+ write_count = 256;
+ }
+ else if( sourcef.size() - written == 256 )
+ {
+ write_count = 256;
+ last_sector_size = 0;
+ }
+ else
+ {
+ write_count = sourcef.size() - written;
+ last_sector_size = write_count;
+ }
+
+ err = imgtool_floppy_write_sector_from_stream(image, head, track, sector, 0, write_count, sourcef);
+ if (err) return err;
+
+ current_sector_index++;
+ written += write_count;
+ }
+
+ if( written == sourcef.size()) // are we are done writing file
+ {
+ int de_count = 0;
+ int de_dont_delete = position;
+ int lsn, count;
+ int save_next_de;
+
+ save_next_de = ent.dngdos_last_or_next;
+ ent.dngdos_last_or_next = last_sector_size;
+
+ // yes, truncate this allocation block if necessary
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT)
+ {
+ for( int i = current_sector_index; i < ent.block.continuation.block[fat_block].count; i++)
+ {
+ dgndos_fat_deallocate_sector(entire_track20, first_lsn + i);
+ }
+
+ ent.block.continuation.block[fat_block].count = current_sector_index;
+ }
+ else
+ {
+ for( int i = current_sector_index; i < ent.block.header.block[fat_block].count; i++)
+ {
+ dgndos_fat_deallocate_sector(entire_track20, first_lsn + i);
+ }
+
+ ent.block.header.block[fat_block].count = current_sector_index;
+ }
+
+ do // check remaining allocation blocks and zero them
+ {
+ fat_block++;
+
+ if( (fat_block < (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT)) )
+ {
+ lsn = big_endianize_int16( ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn );
+ count = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+
+ if( count > 0 )
+ {
+ dgndos_fat_deallocate_span(entire_track20, lsn, count);
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn) = 0;
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = 0;
+ }
+ }
+ else
+ {
+ uint8_t save_flag = ent.flag_byte;
+
+ ent.flag_byte &= ~DGNDOS_CONTINUED_BIT;
+
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT )
+ {
+ if( de_dont_delete != position )
+ {
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ }
+ }
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ if( save_flag & DGNDOS_CONTINUED_BIT )
+ {
+ position = save_next_de;
+
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ save_next_de = ent.dngdos_last_or_next;
+ fat_block = -1;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ de_count++;
+ }
+ while( de_count < MAX_DIRENTS );
+
+ if( de_count == MAX_DIRENTS ) return IMGTOOLERR_CORRUPTDIR;
+ }
+ else // more to write
+ {
+ // check if I can extend the allocation count
+ if( (current_sector_index < 254) && (first_lsn + current_sector_index < bitmap_count) && (dgndos_is_sector_avaiable( entire_track20, first_lsn + current_sector_index )) )
+ {
+ sectors_avaiable++;
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = sectors_avaiable;
+
+ dgndos_fat_allocate_sector( entire_track20, first_lsn + current_sector_index );
+ }
+ else // this allocation list is full - check next allocation list
+ {
+ fat_block++;
+
+ if( fat_block == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT))
+ {
+ if( ent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ // go to next directory entry.
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ position = ent.dngdos_last_or_next;
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err)
+ {
+ return err;
+ }
+
+ fat_block = 0;
+ }
+ else
+ {
+ // need a or another continuation directory entry
+ int save_position = position, new_lsn;
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ err = dgndos_get_avaiable_dirent_position( entire_track20, &position );
+ if (err)
+ {
+ return err;
+ }
+
+ ent.flag_byte |= DGNDOS_CONTINUED_BIT;
+ ent.dngdos_last_or_next = position;
+ err = put_dgndos_dirent(entire_track20, save_position, ent);
+ if (err) return err;
+
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err)
+ {
+ return err;
+ }
+
+ memset( (void *)&ent, 0, sizeof(dgndos_dirent) );
+ ent.flag_byte |= DGNDOS_CONTINUATION_BIT;
+ fat_block = 0;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err)
+ {
+ return err;
+ }
+ }
+ }
+
+ sectors_avaiable = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+
+ // check if this block is empty
+ if( sectors_avaiable == 0)
+ {
+ int new_lsn;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err) return err;
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn) = big_endianize_int16(new_lsn);
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = 1;
+
+ dgndos_fat_allocate_sector(entire_track20, new_lsn);
+ }
+
+ first_lsn = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? big_endianize_int16(ent.block.continuation.block[fat_block].lsn) : big_endianize_int16(ent.block.header.block[fat_block].lsn);
+ sectors_avaiable = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+ current_sector_index = 0;
+ }
+ }
+ }
+ while( written < sourcef.size() );
+
+ ferr = dgndos_put_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if( write_20_to_16 )
+ {
+ ferr = dgndos_put_directory_track( image, 16, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ imgtool::image &image(partition.image());
+ struct dgndos_dirent ent;
+ int pos;
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if (fname)
+ {
+ err = lookup_dgndos_file(entire_track20, fname, ent, &pos);
+ if (err)
+ return err;
+
+ if (strcmp(ent.block.header.filename+8,"DAT") == 0)
+ {
+ /* ASCII file */
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = filter_eoln_getinfo;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
+ }
+ else if (strcmp(ent.block.header.filename+8,"BAS") == 0)
+ {
+ /* tokenized BASIC file */
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = filter_dragonbas_getinfo;
+ }
+ }
+ else
+ {
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = filter_eoln_getinfo;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[2].filter = filter_dragonbas_getinfo;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_create(imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *opts)
+{
+ imgtoolerr_t err;
+ uint32_t heads, tracks, sectors, first_sector_id, sector_bytes, total_sector_count;
+ uint8_t sector[512];
+ struct dgndos_dirent *ents;
+
+ heads = opts->lookup_int('H');
+ tracks = opts->lookup_int('T');
+ sectors = opts->lookup_int('S');
+ first_sector_id = opts->lookup_int('F');
+ sector_bytes = opts->lookup_int('L');
+
+ if(sector_bytes!=256) return IMGTOOLERR_UNIMPLEMENTED;
+
+ // create FAT sectors
+ memset( sector, 0, 512 );
+
+ total_sector_count = (heads * tracks * sectors);
+
+ for( int i=0; i<total_sector_count; i++ )
+ {
+ dgndos_fat_deallocate_sector(sector, i);
+ }
+
+ sector[0xfc] = tracks;
+ sector[0xfd] = heads == 1 ? (sectors) : (sectors * 2);
+ sector[0xfe] = ~sector[0xfc];
+ sector[0xff] = ~sector[0xfd];
+
+ // allocate sectors
+ for( int i=0; i<18; i++ )
+ {
+ dgndos_fat_allocate_sector(sector, (20 * 18 * heads) + i);
+ dgndos_fat_allocate_sector(sector, (16 * 18 * heads) + i);
+ }
+
+ // write fat sectors
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, first_sector_id, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, first_sector_id+1, 0, &sector[256], sector_bytes, 0);
+ if (err) return err;
+
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, first_sector_id, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, first_sector_id+1, 0, &sector[256], sector_bytes, 0);
+ if (err) return err;
+
+ // create empty directory entries
+ memset( sector, 0, 512 );
+ ents = (struct dgndos_dirent *)sector;
+
+ for( int i=0; i<10; i++ )
+ {
+ ents[i].flag_byte = 0x89;
+ }
+
+ // write directory entires to disk
+ for( int i=3; i<19; i++)
+ {
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, i, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, i, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+/*********************************************************************
+ Imgtool module declaration
+*********************************************************************/
+
+OPTION_GUIDE_START( dragon_dgndos_writefile_optionguide )
+ OPTION_ENUM_START( DGNDOS_OPTIONS_PROTECT, "prot", "Protect file" )
+ OPTION_ENUM( 0, "no", "No" )
+ OPTION_ENUM( 1, "yes", "Yes" )
+ OPTION_ENUM_END
+OPTION_GUIDE_END
+
+void dgndos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
+ case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct dgndos_direnum); break;
+
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
+ case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "dgndos"); break;
+ case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Dragon DOS 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;
+ case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "P[0]-1"); 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 = dgndos_diskimage_create; break;
+ case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = dgndos_diskimage_nextenum; break;
+ case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = dgndos_diskimage_freespace; break;
+ case IMGTOOLINFO_PTR_READ_FILE: info->read_file = dgndos_diskimage_readfile; break;
+ case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = dgndos_diskimage_writefile; break;
+ case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = dgndos_diskimage_deletefile; break;
+ case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = dgndos_diskimage_suggesttransfer; break;
+ case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &dragon_dgndos_writefile_optionguide; break;
+ case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break;
+ }
+}
diff --git a/src/tools/imgtool/modules/fat.cpp b/src/tools/imgtool/modules/fat.cpp
index 029050d1e9c..d6611932c0d 100644
--- a/src/tools/imgtool/modules/fat.cpp
+++ b/src/tools/imgtool/modules/fat.cpp
@@ -134,13 +134,17 @@
****************************************************************************/
-#include <time.h>
-#include <ctype.h>
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "unicode.h"
#include "fat.h"
+#include "corestr.h"
+#include "multibyte.h"
+#include "unicode.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <ctime>
+
#define FAT_DIRENT_SIZE 32
#define FAT_SECLEN 512
@@ -176,6 +180,18 @@ struct fat_file
struct fat_dirent
{
+ fat_dirent() :
+ directory(0),
+ eof(0),
+ filesize(0),
+ first_cluster(0),
+ dirent_sector_index(0),
+ dirent_sector_offset(0)
+ {
+ std::fill(std::begin(long_filename), std::end(long_filename), 0);
+ std::fill(std::begin(short_filename), std::end(short_filename), 0);
+ }
+
char long_filename[512];
char short_filename[13];
unsigned int directory : 1;
@@ -364,14 +380,12 @@ static imgtoolerr_t fat_write_sector(imgtool::partition &partition, uint32_t sec
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t fat_clear_sector(imgtool::partition &partition, uint32_t sector_index, uint8_t data)
+[[maybe_unused]] static imgtoolerr_t fat_clear_sector(imgtool::partition &partition, uint32_t sector_index, uint8_t data)
{
char buf[FAT_SECLEN];
memset(buf, data, sizeof(buf));
return fat_write_sector(partition, sector_index, 0, buf, sizeof(buf));
}
-#endif
static imgtoolerr_t fat_partition_open(imgtool::partition &partition, uint64_t first_block, uint64_t block_count)
@@ -410,19 +424,19 @@ static imgtoolerr_t fat_partition_open(imgtool::partition &partition, uint64_t f
}
info->fat_bits = fat_bits;
- sector_size = pick_integer_le(header, 11, 2);
- info->sectors_per_cluster = pick_integer_le(header, 13, 1);
- info->reserved_sectors = pick_integer_le(header, 14, 2);
- info->fat_count = pick_integer_le(header, 16, 1);
- info->root_entries = pick_integer_le(header, 17, 2);
- total_sectors_l = pick_integer_le(header, 19, 2);
- info->sectors_per_fat = pick_integer_le(header, 22, 2);
- total_sectors_h = pick_integer_le(header, 32, 4);
+ sector_size = get_u16le(&header[11]);
+ info->sectors_per_cluster = header[13];
+ info->reserved_sectors = get_u16le(&header[14]);
+ info->fat_count = header[16];
+ info->root_entries = get_u16le(&header[17]);
+ total_sectors_l = get_u16le(&header[19]);
+ info->sectors_per_fat = get_u16le(&header[22]);
+ total_sectors_h = get_u32le(&header[32]);
if (info->sectors_per_cluster == 0)
return IMGTOOLERR_CORRUPTIMAGE;
- info->total_sectors = total_sectors_l + (((uint64_t) total_sectors_h) << 16);
+ info->total_sectors = total_sectors_l + (uint64_t(total_sectors_h) << 16);
available_sectors = info->total_sectors - info->reserved_sectors
- (info->sectors_per_fat * info->fat_count)
- (info->root_entries * FAT_DIRENT_SIZE + FAT_SECLEN - 1) / FAT_SECLEN;
@@ -520,24 +534,24 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
/* prepare the header */
memset(header, 0, sizeof(header));
memcpy(&header[3], "IMGTOOL ", 8);
- place_integer_le(header, 11, 2, FAT_SECLEN);
- place_integer_le(header, 13, 1, sectors_per_cluster);
- place_integer_le(header, 14, 1, reserved_sectors);
- place_integer_le(header, 16, 1, fat_count);
- place_integer_le(header, 17, 2, root_dir_count);
- place_integer_le(header, 19, 2, (uint16_t) (block_count >> 0));
- place_integer_le(header, 21, 1, media_descriptor);
- place_integer_le(header, 22, 2, sectors_per_fat);
- place_integer_le(header, 24, 2, sectors_per_track);
- place_integer_le(header, 26, 2, heads);
- place_integer_le(header, 28, 4, hidden_sectors);
- place_integer_le(header, 32, 4, (uint32_t) (block_count >> 16));
- place_integer_le(header, 36, 1, 0xFF);
- place_integer_le(header, 38, 1, 0x28);
- place_integer_le(header, 39, 1, std::rand());
- place_integer_le(header, 40, 1, std::rand());
- place_integer_le(header, 41, 1, std::rand());
- place_integer_le(header, 42, 1, std::rand());
+ put_u16le(&header[11], FAT_SECLEN);
+ header[13] = sectors_per_cluster;
+ header[14] = reserved_sectors;
+ header[16] = fat_count;
+ put_u16le(&header[17], root_dir_count);
+ put_u16le(&header[19], uint16_t(block_count >> 0));
+ header[21] = media_descriptor;
+ put_u16le(&header[22], sectors_per_fat);
+ put_u16le(&header[24], sectors_per_track);
+ put_u16le(&header[26], heads);
+ put_u32le(&header[28], hidden_sectors);
+ put_u32le(&header[32], uint32_t(block_count >> 16));
+ header[36] = 0xFF;
+ header[38] = 0x28;
+ header[39] = std::rand();
+ header[40] = std::rand();
+ header[41] = std::rand();
+ header[42] = std::rand();
memcpy(&header[43], " ", 11);
memcpy(&header[54], fat_bits_string, 8);
@@ -553,14 +567,14 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
if (boot_sector_offset <= 129)
{
header[0] = 0xEB; /* JMP rel8 */
- header[1] = (uint8_t) (boot_sector_offset - 2); /* (offset) */
+ header[1] = uint8_t(boot_sector_offset - 2); /* (offset) */
header[2] = 0x90; /* NOP */
}
else
{
header[0] = 0xE9; /* JMP rel16 */
- header[1] = (uint8_t) ((boot_sector_offset - 2) >> 0); /* (offset) */
- header[2] = (uint8_t) ((boot_sector_offset - 2) >> 8); /* (offset) */
+ header[1] = uint8_t((boot_sector_offset - 2) >> 0); /* (offset) */
+ header[2] = uint8_t((boot_sector_offset - 2) >> 8); /* (offset) */
}
err = image.write_block(first_block, header);
@@ -578,9 +592,9 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
// FIXME: this causes a corrupt PC floppy image since it doubles the FAT partition header - works without it though
#if 0
/* set first two FAT entries */
- first_fat_entries = ((uint64_t) media_descriptor) | 0xFFFFFF00;
- first_fat_entries &= (((uint64_t) 1) << fat_bits) - 1;
- first_fat_entries |= ((((uint64_t) 1) << fat_bits) - 1) << fat_bits;
+ first_fat_entries = uint64_t(media_descriptor) | 0xFFFFFF00;
+ first_fat_entries &= (uint64_t(1) << fat_bits) - 1;
+ first_fat_entries |= ((uint64_t(1) << fat_bits) - 1) << fat_bits;
first_fat_entries = little_endianize_int64(first_fat_entries);
for (i = 0; i < fat_count; i++)
@@ -706,8 +720,8 @@ static uint32_t fat_get_fat_entry(imgtool::partition &partition, const uint8_t *
entry &= bit_mask;
if (i == 0)
- last_entry = (uint32_t) entry;
- else if (last_entry != (uint32_t) entry)
+ last_entry = uint32_t(entry);
+ else if (last_entry != uint32_t(entry))
return 1; /* if the FATs disagree; mark this as reserved */
}
@@ -739,8 +753,8 @@ static void fat_set_fat_entry(imgtool::partition &partition, uint8_t *fat_table,
* disk_info->sectors_per_fat) + (bit_index / 8), sizeof(entry));
entry = little_endianize_int64(entry);
- entry &= (~((uint64_t) 0xFFFFFFFF >> (32 - disk_info->fat_bits)) << (bit_index % 8)) | ((1 << (bit_index % 8)) - 1);
- entry |= ((uint64_t) value) << (bit_index % 8);
+ entry &= (~(uint64_t(0xFFFFFFFF) >> (32 - disk_info->fat_bits)) << (bit_index % 8)) | ((1 << (bit_index % 8)) - 1);
+ entry |= uint64_t(value) << (bit_index % 8);
entry = little_endianize_int64(entry);
memcpy(fat_table + (i * FAT_SECLEN
@@ -1080,8 +1094,8 @@ static imgtoolerr_t fat_set_file_size(imgtool::partition &partition, fat_file *f
}
/* record the new file size */
- place_integer_le(dirent, 26, 2, file->first_cluster);
- place_integer_le(dirent, 28, 4, new_size);
+ put_u16le(&dirent[26], file->first_cluster);
+ put_u32le(&dirent[28], new_size);
/* delete the file, if appropriate */
if (delete_file)
@@ -1228,7 +1242,7 @@ static void fat_canonicalize_sfn(char *sfn, const uint8_t *sfn_bytes)
memcpy(sfn, sfn_bytes, 8);
rtrim(sfn);
if (sfn[0] == 0x05)
- sfn[0] = (char) 0xE5;
+ sfn[0] = char(0xE5);
if ((sfn_bytes[8] != ' ') || (sfn_bytes[9] != ' ') || (sfn_bytes[10] != ' '))
{
strcat(sfn, ".");
@@ -1272,15 +1286,16 @@ static uint32_t fat_setup_time(time_t ansi_time)
-static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *file,
- fat_dirent &ent, fat_freeentry_info *freeent)
+static imgtoolerr_t fat_read_dirent(
+ imgtool::partition &partition,
+ fat_file *file,
+ fat_dirent &ent,
+ fat_freeentry_info *freeent)
{
imgtoolerr_t err;
//const fat_partition_info *disk_info;
uint8_t entry[FAT_DIRENT_SIZE];
size_t bytes_read;
- int i, j;
- char32_t ch;
char16_t lfn_buf[512];
size_t lfn_len = 0;
int lfn_lastentry = 0;
@@ -1289,7 +1304,7 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
assert(file->directory);
lfn_buf[0] = '\0';
- memset(&ent, 0, sizeof(ent));
+ ent = fat_dirent();
//disk_info = fat_get_partition_info(partition);
/* The first eight bytes of a FAT directory entry is a blank padded name
@@ -1326,11 +1341,11 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
lfn_checksum = entry[13];
}
lfn_lastentry = entry[0] & 0x3F;
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 28, 2);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 14, 6);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 1, 5);
}
else if (freeent && (freeent->position == ~0))
@@ -1350,7 +1365,7 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
}
}
}
- while((entry[0] == 0x2E) || (entry[0] == 0xE5) || (entry[11] == 0x0F));
+ while ((entry[0] == 0x2E) || (entry[0] == 0xE5) || (entry[11] == 0x0F));
/* no more directory entries? */
if (entry[0] == '\0')
@@ -1368,25 +1383,25 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
/* only use the LFN if the checksum passes */
if (lfn_checksum == fat_calc_filename_checksum(entry))
{
- i = 0;
- j = 0;
+ int i = 0, j = 0;
+ char32_t ch;
do
{
- i += uchar_from_utf16(&ch, &lfn_buf[i], ARRAY_LENGTH(lfn_buf) - i);
- j += utf8_from_uchar(&ent.long_filename[j], ARRAY_LENGTH(ent.long_filename) - j, ch);
+ i += uchar_from_utf16(&ch, &lfn_buf[i], std::size(lfn_buf) - i);
+ j += utf8_from_uchar(&ent.long_filename[j], std::size(ent.long_filename) - j, ch);
}
- while(ch != 0);
+ while (ch != 0);
}
}
/* other attributes */
- ent.filesize = pick_integer_le(entry, 28, 4);
+ ent.filesize = get_u32le(&entry[28]);
ent.directory = (entry[11] & 0x10) ? 1 : 0;
- ent.first_cluster = pick_integer_le(entry, 26, 2);
+ ent.first_cluster = get_u16le(&entry[26]);
ent.dirent_sector_index = entry_sector_index;
ent.dirent_sector_offset = entry_sector_offset;
- ent.creation_time = fat_crack_time(pick_integer_le(entry, 14, 4));
- ent.lastmodified_time = fat_crack_time(pick_integer_le(entry, 22, 4));
+ ent.creation_time = fat_crack_time(get_u32le(&entry[14]));
+ ent.lastmodified_time = fat_crack_time(get_u32le(&entry[22]));
return IMGTOOLERR_SUCCESS;
}
@@ -1440,9 +1455,9 @@ static imgtoolerr_t fat_construct_dirent(const char *filename, creation_policy_t
/* set up file dates in the new dirent */
now = fat_setup_time(time(NULL));
- place_integer_le(created_entry, 14, 4, now);
- place_integer_le(created_entry, 18, 2, now);
- place_integer_le(created_entry, 22, 4, now);
+ put_u32le(&created_entry[14], now);
+ put_u16le(&created_entry[18], now);
+ put_u32le(&created_entry[22], now);
while(*filename)
{
@@ -1451,13 +1466,13 @@ static imgtoolerr_t fat_construct_dirent(const char *filename, creation_policy_t
/* append to short filename, if possible */
if ((ch < 32) || (ch > 128))
short_char = '\0';
- else if (isalnum((char) ch))
- short_char = toupper((char) ch);
- else if (strchr(".!#$%^()-@^_`{}~", (char) ch))
- short_char = (char) ch;
+ else if (isalnum(char(ch)))
+ short_char = toupper(char(ch));
+ else if (strchr(".!#$%^()-@^_`{}~", char(ch)))
+ short_char = char(ch);
else
short_char = '\0'; /* illegal SFN char */
- canonical_short_char = fat_canonicalize_sfn_char((char) ch);
+ canonical_short_char = fat_canonicalize_sfn_char(char(ch));
if (!short_char || (short_char != canonical_short_char))
{
if (toupper(short_char) == toupper(canonical_short_char))
@@ -1605,7 +1620,7 @@ static void fat_bump_dirent(imgtool::partition &partition, uint8_t *entry, size_
sfn_entry = &entry[entry_len - FAT_DIRENT_SIZE];
digit_place = 1;
- for (pos = 7; (pos >= 0) && isdigit((char) sfn_entry[pos]); pos--)
+ for (pos = 7; (pos >= 0) && isdigit(char(sfn_entry[pos])); pos--)
{
val += (sfn_entry[pos] - '0') * digit_place;
digit_place *= 10;
@@ -1834,7 +1849,7 @@ static imgtoolerr_t fat_partition_nextenum(imgtool::directory &enumeration, imgt
return err;
/* copy stuff from the FAT dirent to the Imgtool dirent */
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fatent.long_filename[0]
+ snprintf(ent.filename, std::size(ent.filename), "%s", fatent.long_filename[0]
? fatent.long_filename : fatent.short_filename);
ent.filesize = fatent.filesize;
ent.directory = fatent.directory;
@@ -1945,7 +1960,7 @@ static imgtoolerr_t fat_partition_writefile(imgtool::partition &partition, const
if (file.directory)
return IMGTOOLERR_FILENOTFOUND;
- bytes_left = (uint32_t) sourcef.size();
+ bytes_left = uint32_t(sourcef.size());
err = fat_set_file_size(partition, &file, bytes_left);
if (err)
@@ -2051,11 +2066,11 @@ static imgtoolerr_t fat_partition_createdir(imgtool::partition &partition, const
/* set up the two directory entries in all directories */
memset(initial_data, 0, sizeof(initial_data));
memcpy(&initial_data[0], ". ", 11);
- place_integer_le(initial_data, 11, 1, 0x10);
- place_integer_le(initial_data, 26, 2, file.first_cluster);
+ initial_data[11] = 0x10;
+ put_u16le(&initial_data[26], file.first_cluster);
memcpy(&initial_data[32], ". ", 11);
- place_integer_le(initial_data, 43, 1, 0x10);
- place_integer_le(initial_data, 58, 2, file.parent_first_cluster);
+ initial_data[43] = 0x10;
+ put_u16le(&initial_data[58], file.parent_first_cluster);
err = fat_write_file(partition, &file, initial_data, sizeof(initial_data), NULL);
if (err)
diff --git a/src/tools/imgtool/modules/fat.h b/src/tools/imgtool/modules/fat.h
index 77c56f5f9f1..8e7c60d89af 100644
--- a/src/tools/imgtool/modules/fat.h
+++ b/src/tools/imgtool/modules/fat.h
@@ -1,3 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Raphael Nabet
+
+#include "imgtool.h"
+
void fat_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info);
diff --git a/src/tools/imgtool/modules/hp48.cpp b/src/tools/imgtool/modules/hp48.cpp
index 4d237f3c470..4a008adaeb5 100644
--- a/src/tools/imgtool/modules/hp48.cpp
+++ b/src/tools/imgtool/modules/hp48.cpp
@@ -86,6 +86,8 @@
#include "imgtool.h"
+#include "opresolv.h"
+
/*****************************************************************************
diff --git a/src/tools/imgtool/modules/hp85_tape.cpp b/src/tools/imgtool/modules/hp85_tape.cpp
index dada87e290a..319f1e3f10c 100644
--- a/src/tools/imgtool/modules/hp85_tape.cpp
+++ b/src/tools/imgtool/modules/hp85_tape.cpp
@@ -7,12 +7,19 @@
HP-85 tape format
*********************************************************************/
-
#include "imgtool.h"
-#include "formats/imageutl.h"
+
#include "formats/hti_tape.h"
+
+#include "ioprocs.h"
+#include "multibyte.h"
+#include "opresolv.h"
+#include "strformat.h"
+
+#include <cstdio>
#include <iostream>
+
// Constants
static constexpr unsigned CHARS_PER_FNAME = 6; // Characters in a filename
static constexpr unsigned CHARS_PER_EXT = 4; // Characters in (simulated) file extension
@@ -109,9 +116,9 @@ private:
// Content
std::vector<sif_file_ptr_t> content;
// First file on track 1
- file_no_t file_track_1;
+ file_no_t file_track_1{};
// No. of first record on track 1
- uint16_t record_track_1;
+ uint16_t record_track_1 = 0;
bool dec_rec_header(const tape_word_t *hdr , file_no_t& file_no , uint16_t& rec_no , bool& has_body , unsigned& body_len);
bool load_whole_tape();
@@ -145,7 +152,7 @@ typedef struct {
tape_image_85::tape_image_85(void)
: dirty(false)
{
- image.set_bits_per_word(16);
+ image.set_image_format(hti_format_t::HTI_DELTA_MOD_16_BITS);
}
void tape_image_85::format_img(void)
@@ -158,48 +165,13 @@ void tape_image_85::format_img(void)
finalize_allocation();
}
-namespace {
- int my_seekproc(void *file, int64_t offset, int whence)
- {
- reinterpret_cast<imgtool::stream *>(file)->seek(offset, whence);
- return 0;
- }
-
- size_t my_readproc(void *file, void *buffer, size_t length)
- {
- return reinterpret_cast<imgtool::stream *>(file)->read(buffer, length);
- }
-
- size_t my_writeproc(void *file, const void *buffer, size_t length)
- {
- reinterpret_cast<imgtool::stream *>(file)->write(buffer, length);
- return length;
- }
-
- uint64_t my_filesizeproc(void *file)
- {
- return reinterpret_cast<imgtool::stream *>(file)->size();
- }
-
- const struct io_procs my_stream_procs = {
- nullptr,
- my_seekproc,
- my_readproc,
- my_writeproc,
- my_filesizeproc
- };
-}
-
imgtoolerr_t tape_image_85::load_from_file(imgtool::stream *stream)
{
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- if (!image.load_tape(&io)) {
+ auto io = imgtool::stream_read(*stream, 0);
+ if (!io || !image.load_tape(*io)) {
return IMGTOOLERR_READERROR;
}
+ io.reset();
// Prevent track boundary crossing when reading directory
file_track_1 = 0;
@@ -422,12 +394,7 @@ imgtoolerr_t tape_image_85::save_to_file(imgtool::stream *stream)
file_0.clear();
save_sif_file(track , pos , dir.size() + 1 , file_0);
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- image.save_tape(&io);
+ image.save_tape(*imgtool::stream_read_write(*stream, 0));
return IMGTOOLERR_SUCCESS;
}
@@ -667,7 +634,7 @@ bool tape_image_85::decode_dir(const sif_file_t& file_0)
// Get FL1TK1
file_track_1 = file_0[ 0xfd ];
- record_track_1 = pick_integer_le(file_0.data() , 0xfe , 2);
+ record_track_1 = get_u16le(&file_0[ 0xfe ]);
file_no_t file_no = 1;
@@ -698,10 +665,10 @@ bool tape_image_85::decode_dir(const sif_file_t& file_0)
new_entry.file_no = file_no++;
// Physical records
- new_entry.n_recs = pick_integer_le(p , 8 , 2);
+ new_entry.n_recs = get_u16le(&p[ 8 ]);
// Bytes per logical record
- new_entry.record_len = pick_integer_le(p , 10 , 2);
+ new_entry.record_len = get_u16le(&p[ 10 ]);
if (new_entry.record_len < 4 || new_entry.record_len >= 32768) {
return false;
}
@@ -722,8 +689,8 @@ void tape_image_85::encode_dir(sif_file_t& file_0) const
file_0[ 0x1fc ] = 1;
// Set FL1TK1
file_0[ 0xfd ] = file_0[ 0x1fd ] = file_track_1;
- place_integer_le(file_0.data() , 0xfe , 2 , record_track_1);
- place_integer_le(file_0.data() , 0x1fe , 2 , record_track_1);
+ put_u16le(&file_0[ 0xfe ] , record_track_1);
+ put_u16le(&file_0[ 0x1fe ] , record_track_1);
unsigned i = 0;
file_no_t file_no = 1;
@@ -736,8 +703,8 @@ void tape_image_85::encode_dir(sif_file_t& file_0) const
memcpy(&p_entry[ 0 ] , &entry->filename[ 0 ] , CHARS_PER_FNAME);
p_entry[ 6 ] = file_no;
p_entry[ 7 ] = entry->filetype;
- place_integer_le(p_entry , 8 , 2 , entry->n_recs);
- place_integer_le(p_entry , 10 , 2 , entry->record_len);
+ put_u16le(&p_entry[ 8 ] , entry->n_recs);
+ put_u16le(&p_entry[ 10 ] , entry->record_len);
}
if (file_no <= MAX_FILE_NO) {
@@ -866,7 +833,7 @@ namespace {
tape_image_85& get_tape_image(tape_state_t& ts)
{
if (ts.img == nullptr) {
- ts.img = global_alloc(tape_image_85);
+ ts.img = new tape_image_85;
}
return *(ts.img);
@@ -916,7 +883,7 @@ namespace {
delete state.stream;
// Free tape_image
- global_free(&tape_image);
+ delete &tape_image;
}
imgtoolerr_t hp85_tape_begin_enum (imgtool::directory &enumeration, const char *path)
diff --git a/src/tools/imgtool/modules/hp9845_tape.cpp b/src/tools/imgtool/modules/hp9845_tape.cpp
index d3416deaefd..26cb2f4eb1c 100644
--- a/src/tools/imgtool/modules/hp9845_tape.cpp
+++ b/src/tools/imgtool/modules/hp9845_tape.cpp
@@ -108,12 +108,20 @@
these special characters.
*********************************************************************/
-#include <bitset>
-
#include "imgtool.h"
-#include "formats/imageutl.h"
+#include "filter.h"
+
#include "formats/hti_tape.h"
+#include "corefile.h"
+#include "ioprocs.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <bitset>
+#include <cstdio>
+
+
// Constants
#define SECTOR_LEN 256 // Bytes in a sector
#define WORDS_PER_SECTOR (SECTOR_LEN / 2) // 16-bit words in a sector payload
@@ -291,49 +299,16 @@ void tape_image_t::format_img(void)
dirty = true;
}
-static int my_seekproc(void *file, int64_t offset, int whence)
-{
- reinterpret_cast<imgtool::stream *>(file)->seek(offset, whence);
- return 0;
-}
-
-static size_t my_readproc(void *file, void *buffer, size_t length)
-{
- return reinterpret_cast<imgtool::stream *>(file)->read(buffer, length);
-}
-
-static size_t my_writeproc(void *file, const void *buffer, size_t length)
-{
- reinterpret_cast<imgtool::stream *>(file)->write(buffer, length);
- return length;
-}
-
-static uint64_t my_filesizeproc(void *file)
-{
- return reinterpret_cast<imgtool::stream *>(file)->size();
-}
-
-static const struct io_procs my_stream_procs = {
- nullptr,
- my_seekproc,
- my_readproc,
- my_writeproc,
- my_filesizeproc
-};
-
imgtoolerr_t tape_image_t::load_from_file(imgtool::stream *stream)
{
hti_format_t inp_image;
- inp_image.set_bits_per_word(16);
+ inp_image.set_image_format(hti_format_t::HTI_DELTA_MOD_16_BITS);
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- if (!inp_image.load_tape(&io)) {
+ auto io = imgtool::stream_read(*stream, 0);
+ if (!io || !inp_image.load_tape(*io)) {
return IMGTOOLERR_READERROR;
}
+ io.reset();
unsigned exp_sector = 0;
unsigned last_sector_on_track = SECTORS_PER_TRACK;
@@ -523,12 +498,7 @@ imgtoolerr_t tape_image_t::save_to_file(imgtool::stream *stream)
}
}
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- out_image.save_tape(&io);
+ out_image.save_tape(*imgtool::stream_read_write(*stream, 0));
return IMGTOOLERR_SUCCESS;
}
@@ -985,7 +955,7 @@ static tape_state_t& get_tape_state(imgtool::image &img)
static tape_image_t& get_tape_image(tape_state_t& ts)
{
if (ts.img == nullptr) {
- ts.img = global_alloc(tape_image_t);
+ ts.img = new tape_image_t;
}
return *(ts.img);
@@ -1034,7 +1004,7 @@ static void hp9845_tape_close(imgtool::image &image)
delete state.stream;
// Free tape_image
- global_free(&tape_image);
+ delete &tape_image;
}
static imgtoolerr_t hp9845_tape_begin_enum (imgtool::directory &enumeration, const char *path)
@@ -1374,7 +1344,7 @@ static imgtoolerr_t hp9845data_read_file(imgtool::partition &partition, const ch
if (!get_record_part(*inp_data , tmp , 2)) {
return IMGTOOLERR_READERROR;
}
- rec_type = (uint16_t)pick_integer_be(tmp , 0 , 2);
+ rec_type = get_u16be(&tmp[ 0 ]);
switch (rec_type) {
case REC_TYPE_EOR:
// End of record: just skip it
@@ -1397,7 +1367,7 @@ static imgtoolerr_t hp9845data_read_file(imgtool::partition &partition, const ch
if (!get_record_part(*inp_data , tmp , 2)) {
return IMGTOOLERR_READERROR;
}
- tmp_len = (unsigned)pick_integer_be(tmp , 0 , 2);
+ tmp_len = get_u16be(&tmp [ 0 ]);
if (rec_type == REC_TYPE_FULLSTR || rec_type == REC_TYPE_1STSTR) {
accum_len = tmp_len;
@@ -1445,7 +1415,7 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
unsigned free_len = len_to_eor(dest);
if (free_len <= 4) {
// Not enough free space at end of current record: fill with EORs
- place_integer_be(tmp , 0 , 2 , REC_TYPE_EOR);
+ put_u16be(&tmp[ 0 ] , REC_TYPE_EOR);
while (free_len) {
if (dest.write(tmp , 2) != 2) {
return false;
@@ -1458,8 +1428,8 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
// Free space to EOR enough for what's left of string
break;
}
- place_integer_be(tmp , 0 , 2 , rec_type);
- place_integer_be(tmp , 2 , 2 , s_len);
+ put_u16be(&tmp[ 0 ] , rec_type);
+ put_u16be(&tmp[ 2 ] , s_len);
if (dest.write(tmp , 4) != 4 ||
dest.write(s, s_part_len) != s_part_len) {
return false;
@@ -1471,8 +1441,8 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
}
}
- place_integer_be(tmp , 0 , 2 , at_least_one ? REC_TYPE_ENDSTR : REC_TYPE_FULLSTR);
- place_integer_be(tmp , 2 , 2 , s_len);
+ put_u16be(&tmp[ 0 ] , at_least_one ? REC_TYPE_ENDSTR : REC_TYPE_FULLSTR);
+ put_u16be(&tmp[ 2 ] , s_len);
if (dest.write(tmp , 4) != 4 ||
dest.write(s , s_len) != s_len) {
return false;
@@ -1528,7 +1498,7 @@ static imgtoolerr_t hp9845data_write_file(imgtool::partition &partition, const c
// Fill free space of last record with EOFs
unsigned free_len = len_to_eor(*out_data);
uint8_t tmp[ 2 ];
- place_integer_be(tmp , 0 , 2 , REC_TYPE_EOF);
+ put_u16be(&tmp[ 0 ] , REC_TYPE_EOF);
while (free_len) {
if (out_data->write(tmp , 2 ) != 2) {
@@ -1544,7 +1514,7 @@ static imgtoolerr_t hp9845data_write_file(imgtool::partition &partition, const c
return res;
}
-void filter_hp9845data_getinfo(uint32_t state, union filterinfo *info)
+void filter_hp9845data_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch (state) {
case FILTINFO_PTR_READFILE:
diff --git a/src/tools/imgtool/modules/mac.cpp b/src/tools/imgtool/modules/mac.cpp
deleted file mode 100644
index 90c68323f76..00000000000
--- a/src/tools/imgtool/modules/mac.cpp
+++ /dev/null
@@ -1,6439 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- mac.c
-
- Handlers for Classic MacOS images (MFS and HFS formats).
-
- Raphael Nabet, 2003
-
- TODO:
- * add support for HFS write
-
-*****************************************************************************
-
- terminology:
- disk block: 512-byte logical block. With sectors of 512 bytes, one logical
- block is equivalent to one sector; when the sector size is not 512
- bytes, sectors are split or grouped to make 512-byte disk blocks.
- allocation block: The File Manager always allocates logical disk blocks to
- a file in groups called allocation blocks; an allocation block is
- simply a group of consecutive logical blocks. The size of a volume's
- allocation blocks depends on the capacity of the volume; there can be
- at most 4094 (MFS) or 65535 (HFS) allocation blocks on a volume.
- MFS (Macintosh File System): File system used by the early Macintosh. This
- File system does not support folders (you may create folders on a MFS
- disk, but such folders are not implemented on File System level but in
- the Desktop file, and they are just a hint of how programs should list
- files, i.e. you can't have two files with the same name on a volume
- even if they are in two different folders), and it is not adequate for
- large volumes.
- HFS (Hierarchical File System): File system introduced with the HD20
- harddisk, the Macintosh Plus ROMs, and system 3.2 (IIRC). Contrary to
- MFS, it supports hierarchical folders. Also, it is suitable for larger
- volumes.
- HFS+ (HFS Plus): New file system introduced with MacOS 8.1. It has a lot
- in common with HFS, but it supports more allocation blocks (up to 4
- billions IIRC), and many extra features, including longer file names
- (up to 255 UTF-16 Unicode chars).
- tag data: with the GCR encoding, each disk block is associated with a 12
- (3.5" floppies) or 20 (HD20) byte tag record. This tag record contains
- information on the block allocation status (whether it is allocated
- in a file or free, which file is it belongs to, what offset the block
- has in the file). This enables to recover all files whose data blocks
- are still on the disk surface even if the disk catalog has been trashed
- completely (though most file properties, like the name, type and
- logical EOF, are not saved in the tag record and cannot be recovered).
-
- Organization of an MFS volume:
-
- Logical Contents Allocation block
- block
-
- 0 - 1: System startup information
- 2 - m: Master directory block (MDB)
- + allocation block link pointers
- m+1 - n: Directory file
- n+1 - p-2: Other files and free space 0 - ((p-2)-(n+1))/k
- p-1: Alternate MDB
- p: Not used
- usually, k = 2, m = 3, n = 16, p = 799 (SSDD 3.5" floppy)
- with DSDD 3.5" floppy, I assume that p = 1599, but I don't know the other
- values
-
-
- Master Directory Block:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Volume Signature
- 2 4 Creation Date
- 6 4 Last Modification Date
- 10 2 Volume Attributes
- 12 2 Number of Files In Root Directory
- 14 2 First Block of Volume Bitmap
- ...
-
- Links:
- http://developer.apple.com/documentation/mac/Files/Files-99.html
- http://developer.apple.com/documentation/mac/Files/Files-100.html
- http://developer.apple.com/documentation/mac/Files/Files-101.html
- http://developer.apple.com/documentation/mac/Files/Files-102.html
- http://developer.apple.com/documentation/mac/Files/Files-103.html
- http://developer.apple.com/documentation/mac/Files/Files-104.html
- http://developer.apple.com/documentation/mac/Files/Files-105.html
- http://developer.apple.com/documentation/mac/Files/Files-106.html
- http://developer.apple.com/documentation/mac/Devices/Devices-121.html#MARKER-2-169
- http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
-
-*****************************************************************************/
-
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <limits.h>
-#include <stddef.h>
-
-#include "formats/imageutl.h"
-#include "imgtool.h"
-#include "macutil.h"
-#include "iflopimg.h"
-#include "formats/ap_dsk35.h"
-
-/* if 1, check consistency of B-Tree (most of the checks will eventually be
- suppressed when the image is opened as read-only and only enabled when
- the image is opened as read/write) */
-#define BTREE_CHECKS 1
-/* if 1, check consistency of tag data when we are at risk of corrupting the
- disk (file write and allocation) */
-#define TAG_CHECKS 1
-/* if 1, check consistency of tag data when reading files (not recommended
- IMHO) */
-#define TAG_EXTRA_CHECKS 0
-
-#if 0
-#pragma mark MISCELLANEOUS UTILITIES
-#endif
-
-struct UINT16BE
-{
- uint8_t bytes[2];
-};
-
-struct UINT24BE
-{
- uint8_t bytes[3];
-};
-
-struct UINT32BE
-{
- uint8_t bytes[4];
-};
-
-static inline uint16_t get_UINT16BE(UINT16BE word)
-{
- return (word.bytes[0] << 8) | word.bytes[1];
-}
-
-static inline void set_UINT16BE(UINT16BE *word, uint16_t data)
-{
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
-}
-
-#if 0
-static inline uint32_t get_UINT24BE(UINT24BE word)
-{
- return (word.bytes[0] << 16) | (word.bytes[1] << 8) | word.bytes[2];
-}
-
-static inline void set_UINT24BE(UINT24BE *word, uint32_t data)
-{
- word->bytes[0] = (data >> 16) & 0xff;
- word->bytes[1] = (data >> 8) & 0xff;
- word->bytes[2] = data & 0xff;
-}
-#endif
-
-static inline uint32_t get_UINT32BE(UINT32BE word)
-{
- return (word.bytes[0] << 24) | (word.bytes[1] << 16) | (word.bytes[2] << 8) | word.bytes[3];
-}
-
-static inline void set_UINT32BE(UINT32BE *word, uint32_t data)
-{
- word->bytes[0] = (data >> 24) & 0xff;
- word->bytes[1] = (data >> 16) & 0xff;
- word->bytes[2] = (data >> 8) & 0xff;
- word->bytes[3] = data & 0xff;
-}
-
-/*
- Macintosh string: first byte is length
-*/
-typedef uint8_t mac_str27[28];
-typedef uint8_t mac_str31[32];
-typedef uint8_t mac_str63[64];
-typedef uint8_t mac_str255[256];
-
-/*
- Macintosh type/creator code: 4 char value
-*/
-typedef UINT32BE mac_type;
-
-/*
- point record, with the y and x coordinates
-*/
-struct mac_point
-{
- UINT16BE v; /* actually signed */
- UINT16BE h; /* actually signed */
-};
-
-/*
- rect record, with the corner coordinates
-*/
-struct mac_rect
-{
- UINT16BE top; /* actually signed */
- UINT16BE left; /* actually signed */
- UINT16BE bottom;/* actually signed */
- UINT16BE right; /* actually signed */
-};
-
-/*
- FInfo (Finder file info) record
-*/
-struct mac_FInfo
-{
- mac_type type; /* file type */
- mac_type creator; /* file creator */
- UINT16BE flags; /* Finder flags */
- mac_point location; /* file's location in window */
- /* If set to {0, 0}, and the inited flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE fldr; /* MFS: window that contains file */
- /* -3: trash */
- /* -2: desktop */
- /* -1: new folder template?????? */
- /* 0: disk window ("root") */
- /* > 0: specific folder, index of FOBJ resource??? */
- /* The FOBJ resource contains some folder info;
- the name of the resource is the folder name. */
- /* HFS & HFS+:
- System 7: The window in which the file???s icon appears
- System 8: reserved (set to 0) */
-};
-
-/*
- FXInfo (Finder extended file info) record -- not found in MFS
-*/
-struct mac_FXInfo
-{
- UINT16BE iconID; /* System 7: An ID number for the file???s icon; the
- numbers that identify icons are assigned by the
- Finder */
- /* System 8: Reserved (set to 0) */
- UINT16BE reserved[3]; /* Reserved (set to 0) */
- uint8_t script; /* System 7: if high-bit is set, the script code
- for displaying the file name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- uint8_t XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- file onto the desktop, the directory ID of the
- folder from which the user moves the file is
- saved here) */
-};
-
-/*
- DInfo (Finder folder info) record -- not found in MFS
-*/
-struct mac_DInfo
-{
- mac_rect rect; /* Folder's window bounds */
- UINT16BE flags; /* Finder flags, e.g. kIsInvisible, kNameLocked, etc */
- mac_point location; /* Location of the folder in parent window */
- /* If set to {0, 0}, and the initied flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE view; /* System 7: The manner in which folders are
- displayed */
- /* System 8: reserved (set to 0) */
-};
-
-/*
- DXInfo (Finder extended folder info) record -- not found in MFS
-*/
-struct mac_DXInfo
-{
- mac_point scroll; /* Scroll position */
- UINT32BE openChain; /* System 7: chain of directory IDs for open folders */
- /* System 8: reserved (set to 0) */
- uint8_t script; /* System 7: if high-bit is set, the script code
- for displaying the folder name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- uint8_t XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- folder onto the desktop, the directory ID of
- the folder from which the user moves it is
- saved here) */
-};
-
-/*
- defines for FInfo & DInfo flags fields
-*/
-enum
-{
- fif_isOnDesk = 0x0001, /* System 6: set if item is located on desktop (files and folders) */
- /* System 7: Unused (set to 0) */
- fif_color = 0x000E, /* color coding (files and folders) */
- fif_colorReserved = 0x0010, /* System 6: reserved??? */
- /* System 7: Unused (set to 0) */
- fif_requiresSwitchLaunch= 0x0020, /* System 6: ??? */
- /* System 7: Unused (set to 0) */
- fif_isShared = 0x0040, /* Applications files: if set, the */
- /* application can be executed by */
- /* multiple users simultaneously. */
- /* Otherwise, set to 0. */
- fif_hasNoINITs = 0x0080, /* Extensions/Control Panels: if set(?), */
- /* this file contains no INIT */
- /* resource */
- /* Otherwise, set to 0. */
- fif_hasBeenInited = 0x0100, /* System 6: The Finder has recorded information from
- the file???s bundle resource into the desktop
- database and given the file or folder a
- position on the desktop. */
- /* System 7? 8?: Clear if the file contains desktop database */
- /* resources ('BNDL', 'FREF', 'open', 'kind'...) */
- /* that have not been added yet. Set only by the Finder */
- /* Reserved for folders - make sure this bit is cleared for folders */
-
- /* bit 0x0200 was at a point (AOCE for system 7.x?) the letter bit for
- AOCE, but was reserved before and it is reserved again in recent MacOS
- releases. */
-
- fif_hasCustomIcon = 0x0400, /* (files and folders) */
- fif_isStationery = 0x0800, /* System 7: (files only) */
- fif_nameLocked = 0x1000, /* (files and folders) */
- fif_hasBundle = 0x2000, /* Files only */
- fif_isInvisible = 0x4000, /* (files and folders) */
- fif_isAlias = 0x8000 /* System 7: (files only) */
-};
-
-/*
- mac_to_c_strncpy()
-
- Encode a macintosh string as a C string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): C string
- n (I): length of buffer pointed to by dst
- src (I): macintosh string (first byte is length)
-*/
-static void mac_to_c_strncpy(char *dst, int n, uint8_t *src)
-{
- size_t len = src[0];
- int i, j;
-
- i = j = 0;
- while ((i < len) && (j < n-1))
- {
- switch (src[i+1])
- {
- case '\0':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '0';
- dst[j+2] = '0';
- j += 3;
- break;
-
- case '%':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '2';
- dst[j+2] = '5';
- j += 3;
- break;
-
- default:
- dst[j] = src[i+1];
- j++;
- break;
- }
- i++;
- }
-
-exit:
- if (n > 0)
- dst[j] = '\0';
-}
-
-/*
- c_to_mac_strncpy()
-
- Decode a C string to a macintosh string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): macintosh string (first byte is length)
- src (I): C string
- n (I): length of string pointed to by src
-*/
-static void c_to_mac_strncpy(mac_str255 dst, const char *src, int n)
-{
- size_t len;
- int i;
- char buf[3];
-
-
- len = 0;
- i = 0;
- while ((i < n) && (len < 255))
- {
- switch (src[i])
- {
- case '%':
- if (i >= n-2)
- goto exit;
- buf[0] = src[i+1];
- buf[1] = src[i+2];
- buf[2] = '\0';
- dst[len+1] = strtoul(buf, NULL, 16);
- i += 3;
- break;
-
- default:
- dst[len+1] = src[i];
- i++;
- break;
- }
- len++;
- }
-
-exit:
- dst[0] = len;
-}
-
-/*
- mac_strcmp()
-
- Compare two macintosh strings
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-#ifdef UNUSED_FUNCTION
-static int mac_strcmp(const uint8_t *s1, const uint8_t *s2)
-{
- size_t common_len;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- return memcmp(s1+1, s2+1, common_len) || ((int)s1[0] - s2[0]);
-}
-#endif
-
-/*
- mac_stricmp()
-
- Compare two macintosh strings in a manner compatible with the macintosh HFS
- file system.
-
- This functions emulates the way HFS (and MFS???) sorts string: this is
- equivalent to the RelString macintosh toolbox call with the caseSensitive
- parameter as false and the diacSensitive parameter as true.
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-
-Known issues:
- Using this function makes sense with the MacRoman encoding, as it means the
- computer will regard "DeskTop File", "Desktop File", "Desktop file", etc,
- as the same file. (UNIX users will probably regard this as an heresy, but
- you must consider that, unlike UNIX, the Macintosh was not designed for
- droids, but error-prone human beings that may forget about case.)
-
- (Also, letters with diatrical signs follow the corresponding letters
- without diacritical signs in the HFS catalog file. This does not matter,
- though, since the Finder will not display files in the HFS catalog order,
- but it will instead sort files according to whatever order is currently
- selected in the View menu.)
-
- However, with other text encodings, the behavior will be completely absurd.
- For instance, with the Greek encoding, it will think that the degree symbol
- is the same letter (with different case) as the upper-case Psi, so that if
- a program asks for a file called "90??" on a greek HFS volume, and there is
- a file called "90??" on this volume, file "90??" will be opened.
- Results will probably be even weirder with 2-byte scripts like Japanese or
- Chinese. Of course, we are not going to fix this issue, since doing so
- would break the compatibility with the original Macintosh OS.
-*/
-
-static int mac_stricmp(const uint8_t *s1, const uint8_t *s2)
-{
- static const unsigned char mac_char_sort_table[256] =
- {
- /* \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- /* \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f */
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- /* \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f */
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- /* \x20 \x21 \x22 \x23 \x24 \x25 \x26 \x27 */
- 0x20, 0x21, 0x22, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- /* \x28 \x29 \x2a \x2b \x2c \x2d \x2e \x2f */
- 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- /* \x30 \x31 \x32 \x33 \x34 \x35 \x36 \x37 */
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
- /* \x38 \x39 \x3a \x3b \x3c \x3d \x3e \x3f */
- 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- /* \x40 \x41 \x42 \x43 \x44 \x45 \x46 \x47 */
- 0x46, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x48 \x49 \x4a \x4b \x4c \x4d \x4e \x4f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x50 \x51 \x52 \x53 \x54 \x55 \x56 \x57 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x58 \x59 \x5a \x5b \x5c \x5d \x5e \x5f */
- 0x7e, 0x7f, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
- /* \x60 \x61 \x62 \x63 \x64 \x65 \x66 \x67 */
- 0x4d, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x68 \x69 \x6a \x6b \x6c \x6d \x6e \x6f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x70 \x71 \x72 \x73 \x74 \x75 \x76 \x77 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x78 \x79 \x7a \x7b \x7c \x7d \x7e \x7f */
- 0x7e, 0x7f, 0x81, 0x87, 0x88, 0x89, 0x8a, 0x8b,
- /* \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 */
- 0x49, 0x4b, 0x53, 0x56, 0x67, 0x69, 0x78, 0x4e,
- /* \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f */
- 0x48, 0x4f, 0x49, 0x4a, 0x4b, 0x53, 0x56, 0x57,
- /* \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 */
- 0x58, 0x59, 0x5e, 0x5f, 0x60, 0x61, 0x67, 0x6d,
- /* \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f */
- 0x6e, 0x6f, 0x69, 0x6a, 0x79, 0x7a, 0x7b, 0x78,
- /* \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 */
- 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x75,
- /* \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf */
- 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x4c, 0x6b,
- /* \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 */
- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
- /* \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf */
- 0xa1, 0xa2, 0xa3, 0x50, 0x70, 0xa4, 0x4c, 0x6b,
- /* \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 */
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0x25,
- /* \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf */
- 0x26, 0xac, 0x20, 0x48, 0x4a, 0x6a, 0x6c, 0x6c,
- /* \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 */
- 0xad, 0xae, 0x23, 0x24, 0x2c, 0x2d, 0xaf, 0xb0,
- /* \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf */
- 0x80, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- /* \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- /* \xe8 \xe9 \xea \xeb \xec \xed \xee \xef */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- /* \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 */
- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- /* \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
- };
-
- size_t common_len;
- int i;
- int c1, c2;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- for (i=0; i<common_len; i++)
- {
- c1 = mac_char_sort_table[s1[i+1]];
- c2 = mac_char_sort_table[s2[i+1]];
- if (c1 != c2)
- return c1 - c2;
- }
-
- return ((int)s1[0] - s2[0]);
-}
-
-/*
- mac_strcpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- src (I): source macintosh string (first byte is length)
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-static inline void mac_strcpy(uint8_t *dest, const uint8_t *src)
-{
- memcpy(dest, src, src[0]+1);
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_strncpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- n (I): max string length for dest (range 0-255, buffer length + 1)
- src (I): source macintosh string (first byte is length)
-*/
-static void mac_strncpy(uint8_t *dest, int n, const uint8_t *src)
-{
- size_t len;
-
- len = src[0];
- if (len > n)
- len = n;
- dest[0] = len;
- memcpy(dest+1, src+1, len);
-}
-#endif
-
-/*
- disk image reference
-*/
-struct mac_l1_imgref
-{
- imgtool::image *image;
- uint32_t heads;
-};
-
-
-
-static imgtoolerr_t mac_find_block(mac_l1_imgref *image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector)
-{
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(*image->image), *track) * image->heads))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(*image->image), (*track)++) * image->heads);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(*image->image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(*image->image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- image_read_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where block data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_block(mac_l1_imgref *image, uint32_t block, void *dest)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(*image->image), head, track, sector, 0, dest, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_write_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the block data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_block(mac_l1_imgref *image, uint32_t block, const void *src)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(*image->image), head, track, sector, 0, src, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_get_tag_len()
-
- Get length of tag data (12 for GCR floppies, 20 for HD20, 0 otherwise)
-
- image (I/O): level-1 image reference
-
- Return tag length
-*/
-static inline int image_get_tag_len(mac_l1_imgref *image)
-{
- return 0;
-}
-
-
-
-/*
- image_read_tag()
-
- Read a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where tag data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_tag(mac_l1_imgref *image, uint32_t block, void *dest)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- image_write_tag()
-
- Write a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the tag data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_tag(mac_l1_imgref *image, uint32_t block, const void *src)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS/HFS WRAPPERS
-#endif
-
-enum mac_format
-{
- L2I_MFS,
- L2I_HFS
-};
-
-enum mac_forkID { data_fork = 0x00, rsrc_fork = 0xff };
-
-/*
- MFS image ref
-*/
-struct mfs_l2_imgref
-{
- uint16_t dir_num_files;
- uint16_t dir_start;
- uint16_t dir_blk_len;
-
- uint16_t ABStart;
-
- mac_str27 volname;
-
- unsigned char ABlink_dirty[13]; /* dirty flag for each disk block in the ABlink array */
- uint8_t ABlink[6141];
-};
-
-/*
- HFS extent descriptor
-*/
-struct hfs_extent
-{
- UINT16BE stABN; /* first allocation block */
- UINT16BE numABlks; /* number of allocation blocks */
-};
-
-/*
- HFS likes to group extents by 3 (it is 8 with HFS+), so we create a
- specific type.
-*/
-typedef hfs_extent hfs_extent_3[3];
-
-/*
- MFS open file ref
-*/
-struct mfs_fileref
-{
- uint16_t stBlk; /* first allocation block of file */
-};
-
-/*
- HFS open file ref
-*/
-struct hfs_fileref
-{
- hfs_extent_3 extents; /* first 3 file extents */
-
- uint32_t parID; /* CNID of parent directory (undefined for extent & catalog files) */
- mac_str31 filename; /* file name (undefined for extent & catalog files) */
-};
-
-struct mac_l2_imgref;
-
-/*
- MFS/HFS open file ref
-*/
-struct mac_fileref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
-
- uint32_t fileID; /* file ID (a.k.a. CNID in HFS/HFS+) */
-
- mac_forkID forkType; /* 0x00 for data, 0xff for resource */
-
- uint32_t eof; /* logical end-of-file */
- uint32_t pLen; /* physical end-of-file */
-
- uint32_t crPs; /* current position in file */
-
- uint8_t reload_buf;
- uint8_t block_buffer[512]; /* buffer with current file block */
-
- union
- {
- mfs_fileref mfs;
- hfs_fileref hfs;
- };
-};
-
-/*
- open BT ref
-*/
-struct mac_BTref
-{
- struct mac_fileref fileref; /* open B-tree file ref */
-
- uint16_t nodeSize; /* size of a node, in bytes */
- uint32_t rootNode; /* node number of root node */
- uint32_t firstLeafNode; /* node number of first leaf node */
- uint32_t attributes; /* persistent attributes about the tree */
- uint16_t treeDepth; /* maximum height (usually leaf nodes) */
- uint16_t maxKeyLength; /* maximum key length */
-
- /* function to compare keys during tree searches */
- int (*key_compare_func)(const void *key1, const void *key2);
-
- void *node_buf; /* current node buffer */
-};
-
-/*
- Constants for BTHeaderRec attributes field
-*/
-enum
-{
- btha_badCloseMask = 0x00000001, /* reserved */
- btha_bigKeysMask = 0x00000002, /* key length field is 16 bits */
- btha_variableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length */
-};
-
-/*
- HFS image ref
-*/
-struct hfs_l2_imgref
-{
- uint16_t VBM_start;
-
- uint16_t ABStart;
-
- mac_str27 volname;
-
- mac_BTref extents_BT;
- mac_BTref cat_BT;
-
- uint8_t VBM[8192];
-};
-
-/*
- MFS/HFS image ref
-*/
-struct mac_l2_imgref
-{
- mac_l1_imgref l1_img;
-
- uint16_t numABs;
- uint16_t blocksperAB;
-
- uint16_t freeABs;
-
- uint32_t nxtCNID; /* nxtFNum in MFS, nxtCNID in HFS */
-
- mac_format format;
- union
- {
- mfs_l2_imgref mfs;
- hfs_l2_imgref hfs;
- } u;
-};
-
-/*
- MFS Master Directory Block
-*/
-struct mfs_mdb
-{
- uint8_t sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod/*lsBkUp???*/;/* date and time of last modification (backup???) */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in directory */
- UINT16BE dirSt; /* first block of directory */
-
- UINT16BE blLn; /* length of directory in blocks (0x000C) */
- UINT16BE nmAlBlks; /* number of allocation blocks in volume (0x0187) */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks (0x00000400) */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows (0x00002000) */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
-
- UINT32BE nxtFNum; /* next unused file number */
- UINT16BE freeABs; /* number of unused allocation blocks */
-
- mac_str27 VN; /* volume name */
-
- uint8_t ABlink[512-64];/* Link array for file ABs. Array of nmAlBlks
- 12-bit-long entries, indexed by AB address. If an
- AB belongs to no file, the entry is 0; if an AB is
- the last in any file, the entry is 1; if an AB
- belongs to a file and is not the last one, the
- entry is the AB address of the next file AB plus 1.
- Note that the array extends on as many consecutive
- disk blocks as needed (usually the MDB block plus
- the next one). Incidentally, this array is not
- saved in the secondary MDB: presumably, the idea
- was that the disk utility could rely on the tag
- data to rebuild the link array if it should ever
- be corrupted. */
-};
-
-/*
- HFS Master Directory Block
-*/
-struct hfs_mdb
-{
-/* First fields are similar to MFS, though several fields have a different meaning */
- uint8_t sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod; /* date and time of last modification */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in root folder */
- UINT16BE VBMSt; /* first block of volume bitmap */
- UINT16BE allocPtr; /* start of next allocation search */
-
- UINT16BE nmAlBlks; /* number of allocation blocks in volume */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
- UINT32BE nxtCNID; /* next unused catalog node ID */
- UINT16BE freeABs; /* number of unused allocation blocks */
- mac_str27 VN; /* volume name */
-
-/* next fields are HFS-specific */
-
- UINT32BE volBkUp; /* date and time of last backup */
- UINT16BE vSeqNum; /* volume backup sequence number */
- UINT32BE wrCnt; /* volume write count */
- UINT32BE xtClpSiz; /* clump size for extents overflow file */
- UINT32BE ctClpSiz; /* clump size for catalog file */
- UINT16BE nmRtDirs; /* number of directories in root folder */
- UINT32BE filCnt; /* number of files in volume */
- UINT32BE dirCnt; /* number of directories in volume */
- uint8_t fndrInfo[32]; /* information used by the Finder */
-
- union
- {
- struct
- {
- UINT16BE VCSize; /* size (in blocks) of volume cache */
- UINT16BE VBMCSize; /* size (in blocks) of volume bitmap cache */
- UINT16BE ctlCSize; /* size (in blocks) of common volume cache */
- };
- struct
- {
- UINT16BE embedSigWord; /* embedded volume signature */
- hfs_extent embedExtent; /* embedded volume location and size */
- } v2;
- } u;
-
- UINT32BE xtFlSize; /* size (in bytes) of extents overflow file */
- hfs_extent_3 xtExtRec; /* extent record for extents overflow file */
- UINT32BE ctFlSize; /* size (in bytes) of catalog file */
- hfs_extent_3 ctExtRec; /* extent record for catalog file */
-};
-
-/* to save a little stack space, we use the same buffer for MDB and next blocks */
-union img_open_buf
-{
- struct mfs_mdb mfs_mdb;
- struct hfs_mdb hfs_mdb;
- uint8_t raw[512];
-};
-
-/*
- Information extracted from catalog/directory
-*/
-struct mac_dirent
-{
- uint16_t dataRecType; /* type of data record */
-
- mac_FInfo flFinderInfo; /* information used by the Finder */
- mac_FXInfo flXFinderInfo; /* information used by the Finder */
-
- uint8_t flags; /* bit 0=1 if file locked */
-
- uint32_t fileID; /* file ID in directory/catalog */
-
- uint32_t dataLogicalSize; /* logical EOF of data fork */
- uint32_t dataPhysicalSize; /* physical EOF of data fork */
- uint32_t rsrcLogicalSize; /* logical EOF of resource fork */
- uint32_t rsrcPhysicalSize; /* physical EOF of resource fork */
-
- uint32_t createDate; /* date and time of creation */
- uint32_t modifyDate; /* date and time of last modification */
-};
-
-/*
- Tag record for GCR floppies (12 bytes)
-
- And, no, I don't know the format of the 20-byte tag record of the HD20
-*/
-struct floppy_tag_record
-{
- UINT32BE fileID; /* a.k.a. CNID */
- /* a value of 1 seems to be the default for non-AB blocks, but this is not consistent */
- uint8_t ftype; /* bit 1 = 1 if resource fork */
- /* bit 0 = 1 if block is allocated to user file (i.e. it is not
- in HFS extent & catalog, and not in non-AB blocks such
- as MDB and MFS directory)??? */
- /* bit 7 seems to be used, but I don't know what it means */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- uint8_t fattr; /* bit 0 = 1 if locked(?) */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- UINT16BE fblock; /* relative file block number (enough for any volume up to 32 MBytes in size) */
- UINT32BE wrCnt; /* MFS: date and time of last write */
- /* HFS: seems related to the wrCnt field in the mdb, i.e.
- each time a volume is written to, the current value of
- wrCnt is written in the tag field, then it is incremented */
- /* (DV17 says "disk block number", but it cannot be true) */
-};
-
-#ifdef UNUSED_FUNCTION
-static void hfs_image_close(struct mac_l2_imgref *l2_img);
-#endif
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address);
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address);
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it);
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info);
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, uint32_t newABeof);
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref);
-
-static struct mac_l2_imgref *get_imgref(imgtool::image &img)
-{
- return (struct mac_l2_imgref *) imgtool_floppy_extrabytes(img);
-}
-
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_image_close
-
- Close a macintosh image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void mac_image_close(struct mac_l2_imgref *l2_img)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- break;
-
- case L2I_HFS:
- hfs_image_close(l2_img);
- break;
- }
-}
-#endif
-
-/*
- mac_lookup_path
-
- Resolve a file path, and translate it to a parID + filename pair that enables
- to do an efficient file search on a HFS volume (and an inefficient one on
- MFS, but it is not an issue as MFS volumes typically have a few dozens
- files, vs. possibly thousands with HFS volumes).
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the parent directory if the volume is in HFS
- format (reserved for MFS volumes)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- switch (l2_img->format)
- {
- case L2I_MFS:
- *parID = 0;
- err = mfs_lookup_path(l2_img, fpath, filename, cat_info, create_it);
- break;
-
- case L2I_HFS:
- err = hfs_lookup_path(l2_img, fpath, parID, filename, cat_info);
- break;
- }
- return err;
-}
-
-/*
- mac_file_open
-
- Open a file located on a macintosh image
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of the parent directory if the volume is in HFS format
- (reserved for MFS volumes)
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- return mfs_file_open(l2_img, filename, fork, fileref);
-
- case L2I_HFS:
- return hfs_file_open(l2_img, parID, filename, fork, fileref);
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- mac_file_read
-
- Read data from an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_read(struct mac_fileref *fileref, uint32_t len, void *dest)
-{
- uint32_t block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- if (fileref->reload_buf)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = false;
-
- if (TAG_EXTRA_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(dest, fileref->block_buffer+(fileref->crPs % 512), run_len);
- len -= run_len;
- dest = (uint8_t *)dest + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = true;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_write
-
- Write data to an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_write(struct mac_fileref *fileref, uint32_t len, const void *src)
-{
- uint32_t block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
-
- if (fileref->reload_buf)
- {
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = false;
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(fileref->block_buffer+(fileref->crPs % 512), src, run_len);
- err = image_write_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- /* update tag data */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- if (!TAG_CHECKS)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- break;
-
- case L2I_HFS:
- /*set_UINT32BE(&tag.wrCnt, ++fileref->l2_img.u.hfs.wrCnt);*/ /* ***TODO*** */
- break;
- }
-
- err = image_write_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
- len -= run_len;
- src = (const uint8_t *)src + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = true;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_file_tell
-
- Get current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (O): current position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_tell(struct mac_fileref *fileref, uint32_t *filePos)
-{
- *filePos = fileref->crPs;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-/*
- mac_file_seek
-
- Set current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (I): new position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seek(struct mac_fileref *fileref, uint32_t filePos)
-{
- if ((fileref->crPs / 512) != (filePos / 512))
- fileref->reload_buf = true;
-
- fileref->crPs = filePos;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_seteof
-
- Set the position of the EOF in an open mac file
-
- fileref (I/O): mac file reference
- newEof (I): new position of EOF in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seteof(struct mac_fileref *fileref, uint32_t newEof)
-{
- uint32_t newABEof;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- newABEof = (newEof + fileref->l2_img->blocksperAB * 512 - 1) / (fileref->l2_img->blocksperAB * 512);
-
-#if 0
- if (fileref->pLen % (fileref->l2_img->blocksperAB * 512))
- return IMGTOOLERR_CORRUPTIMAGE;
-#endif
-
- if (newEof < fileref->eof)
- fileref->eof = newEof;
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_setABeof(fileref, newABEof);
- break;
-
- case L2I_HFS:
- err = IMGTOOLERR_UNIMPLEMENTED;
- break;
- }
- if (err)
- return err;
-
- fileref->eof = newEof;
-
- err = mfs_dir_update(fileref);
- if (err)
- return err;
-
- /* update current pos if beyond new EOF */
-#if 0
- if (fileref->crPs > newEof)
- {
- if ((fileref->crPs / 512) != (newEof / 512))
- fileref->reload_buf = true;
-
- fileref->crPs = newEof;
- }
-#endif
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS IMPLEMENTATION
-#endif
-
-/*
- directory entry for use in the directory file
-
- Note the structure is variable length. It is always word-aligned, and
- cannot cross block boundaries.
-
- Note that the directory does not seem to be sorted: the order in which
- files appear does not match file names, and it does not always match file
- IDs.
-*/
-struct mfs_dir_entry
-{
- uint8_t flags; /* bit 7=1 if entry used, bit 0=1 if file locked */
- /* 0x00 means end of block: if we are not done
- with reading the directory, the remnants will
- be read from next block */
- uint8_t flVersNum; /* version number (usually 0x00, but I don't
- have the IM volume that describes it) */
- mac_FInfo flFinderInfo; /* information used by the Finder */
-
- UINT32BE fileID; /* file ID */
-
- UINT16BE dataStartBlock; /* first allocation block of data fork */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* first allocation block of resource fork */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
-
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
-
- uint8_t name[1]; /* first char is length of file name */
- /* next chars are file name - 255 chars at most */
- /* IIRC, Finder 7 only supports 31 chars,
- wheareas earlier versions support 63 chars */
-};
-
-/*
- FOBJ desktop resource: describes a folder, or the location of the volume
- icon.
-
- In typical Apple manner, this resource is not documented. However, I have
- managed to reverse engineer some parts of it.
-*/
-struct mfs_FOBJ
-{
- uint8_t unknown0[2]; /* $00: $0004 for disk, $0008 for folder??? */
- mac_point location; /* $02: location in parent window */
- uint8_t unknown1[4]; /* $06: ??? */
- uint8_t view; /* $0A: manner in which folders are displayed??? */
- uint8_t unknown2; /* $0B: ??? */
- UINT16BE par_fldr; /* $0C: parent folder ID */
- uint8_t unknown3[10]; /* $0E: ??? */
- UINT16BE unknown4; /* $18: ??? */
- UINT32BE createDate; /* $1A: date and time of creation */
- UINT32BE modifyDate; /* $1E: date and time of last modification */
- UINT16BE unknown5; /* $22: put-away folder ID?????? */
- uint8_t unknown6[8]; /* $24: ??? */
- mac_rect bounds; /* $2C: window bounds */
- mac_point scroll; /* $34: current scroll offset??? */
- union
- { /* I think there are two versions of the structure */
- struct
- {
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- UINT32BE item_descs[1]; /* this variable-length array has
- item_count entries - meaning of entry is unknown */
- } v1;
- struct
- {
- UINT16BE zerofill; /* always 0? */
- UINT16BE unknown0; /* always 0??? */
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- uint8_t unknown1[20]; /* ??? */
- uint8_t name[1]; /* variable-length macintosh string */
- } v2;
- } u;
-};
-
-/*
- MFS open dir ref
-*/
-struct mfs_dirref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
- uint16_t index; /* current file index in the disk directory */
- uint16_t cur_block; /* current block offset in directory file */
- uint16_t cur_offset; /* current byte offset in current block of directory file */
- uint8_t block_buffer[512]; /* buffer with current directory block */
-};
-
-
-
-static imgtoolerr_t mfs_image_create(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- uint8_t buffer[512];
- uint32_t heads, tracks, sector_bytes, i;
- uint32_t total_disk_blocks, total_allocation_blocks, allocation_block_size;
- uint32_t free_allocation_blocks;
-
- heads = opts->lookup_int('H');
- tracks = opts->lookup_int('T');
- sector_bytes = opts->lookup_int('L');
-
- get_imgref(image)->l1_img.image = &image;
- get_imgref(image)->l1_img.heads = heads;
-
- if (sector_bytes != 512)
- return IMGTOOLERR_UNEXPECTED;
-
- /* computation */
- allocation_block_size = 1024;
- total_disk_blocks = 0;
- for (i = 0; i < tracks; i++)
- total_disk_blocks += heads * apple35_sectors_per_track(imgtool_floppy(image), i) * sector_bytes / 512;
- total_allocation_blocks = total_disk_blocks / (allocation_block_size / 512);
- free_allocation_blocks = total_allocation_blocks - 3;
-
- /* write master directory block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_be(buffer, 0, 2, 0xd2d7); /* signature */
- place_integer_be(buffer, 2, 4, mac_time_now()); /* creation date */
- place_integer_be(buffer, 6, 4, mac_time_now()); /* last modified date */
- place_integer_be(buffer, 10, 2, 0); /* volume attributes */
- place_integer_be(buffer, 12, 2, 0); /* number of files in directory */
- place_integer_be(buffer, 14, 2, 4); /* first block of directory */
- place_integer_be(buffer, 16, 2, 12); /* length of directory in blocks */
- place_integer_be(buffer, 18, 2, total_allocation_blocks); /* allocation blocks on volume count */
- place_integer_be(buffer, 20, 4, allocation_block_size); /* allocation block size */
- place_integer_be(buffer, 24, 4, 8192); /* default clumping size */
- place_integer_be(buffer, 28, 2, 16); /* first allocation block on volume */
- place_integer_be(buffer, 30, 4, 2); /* next unused catalog node */
- place_integer_be(buffer, 34, 2, free_allocation_blocks); /* free allocation block count */
- pascal_from_c_string(&buffer[36], 28, "Untitled"); /* volume title */
-
- err = image_write_block(&get_imgref(image)->l1_img, 2, buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- mfs_image_open
-
- Open a MFS image. Image must already be open on level 1. This function
- should not be called directly: call mac_image_open() instead.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_image_open(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = &image;
- l2_img->l1_img.heads = 1;
- l2_img->format = L2I_MFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->mfs_mdb.sigWord[0] != 0xd2) || (buf->mfs_mdb.sigWord[1] != 0xd7)
- || (buf->mfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.mfs.dir_num_files = get_UINT16BE(buf->mfs_mdb.nmFls);
- l2_img->u.mfs.dir_start = get_UINT16BE(buf->mfs_mdb.dirSt);
- l2_img->u.mfs.dir_blk_len = get_UINT16BE(buf->mfs_mdb.blLn);
-
- l2_img->numABs = get_UINT16BE(buf->mfs_mdb.nmAlBlks);
- if ((get_UINT32BE(buf->mfs_mdb.alBlkSiz) % 512) || (get_UINT32BE(buf->mfs_mdb.alBlkSiz) == 0))
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->mfs_mdb.alBlkSiz) / 512;
- l2_img->u.mfs.ABStart = get_UINT16BE(buf->mfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->mfs_mdb.nxtFNum);
-
- l2_img->freeABs = get_UINT16BE(buf->mfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.mfs.volname, buf->mfs_mdb.VN);
-
- if (l2_img->numABs > 4094)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte;
- int cur_block;
- int block_len = sizeof(buf->mfs_mdb.ABlink);
-
- /* clear dirty flags */
- for (cur_block=0; cur_block<13; cur_block++)
- l2_img->u.mfs.ABlink_dirty[cur_block] = 0;
-
- /* append the chunk after MDB to link array */
- cur_byte = 0;
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->mfs_mdb.ABlink, block_len);
- cur_byte += block_len;
- cur_block = 2;
- while (cur_byte < byte_len)
- {
- /* read next block */
- cur_block++;
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- block_len = 512;
-
- /* append this block to link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->raw, block_len);
- cur_byte += block_len;
- }
- /* check that link array and directory don't overlap */
- if (cur_block >= l2_img->u.mfs.dir_start)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_update_mdb
-
- Update MDB on disk
-
- l2_img (I/O): level-2 image reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_update_mdb(struct mac_l2_imgref *l2_img)
-{
- imgtoolerr_t err;
- union
- {
- struct mfs_mdb mfs_mdb;
- uint8_t raw[512];
- } buf;
-
- assert(l2_img->format == L2I_MFS);
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- set_UINT16BE(&buf.mfs_mdb.nmFls, l2_img->u.mfs.dir_num_files);
-#if 0 /* these fields are never changed */
- set_UINT16BE(&buf.mfs_mdb.dirSt, l2_img->u.mfs.dir_start);
- set_UINT16BE(&buf.mfs_mdb.blLn, l2_img->u.mfs.dir_blk_len);
-
- set_UINT16BE(&buf.mfs_mdb.nmAlBlks, l2_img->numABs);
- set_UINT32BE(&buf.mfs_mdb.alBlkSiz, l2_img->blocksperAB*512);
- set_UINT16BE(&buf.mfs_mdb.alBlSt, l2_img->u.mfs.ABStart);
-#endif
-
- set_UINT32BE(&buf.mfs_mdb.nxtFNum, l2_img->nxtCNID);
-
- set_UINT16BE(&buf.mfs_mdb.freeABs, l2_img->freeABs);
-
-#if 0 /* these fields are never changed */
- mac_strcpy(buf.mfs_mdb.VN, l2_img->u.mfs.volname);
-#endif
-
- /* save link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte = 0;
- int cur_block = 2;
- int block_len = sizeof(buf.mfs_mdb.ABlink);
-
- /* update the chunk of link array after the MDB */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(buf.mfs_mdb.ABlink, l2_img->u.mfs.ABlink+cur_byte, block_len);
- cur_byte += block_len;
-
- if (block_len < sizeof(buf.mfs_mdb.ABlink))
- memset(buf.mfs_mdb.ABlink+block_len, 0, sizeof(buf.mfs_mdb.ABlink)-block_len);
-
- l2_img->u.mfs.ABlink_dirty[0] = 0;
-
- /* write back modified MDB+link */
- err = image_write_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- while (cur_byte < byte_len)
- {
- /* advance to next block */
- cur_block++;
- block_len = 512;
-
- /* extract the current chunk of link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
-
- if (l2_img->u.mfs.ABlink_dirty[cur_block-2])
- {
- memcpy(buf.raw, l2_img->u.mfs.ABlink+cur_byte, block_len);
- if (block_len < 512)
- memset(buf.raw+block_len, 0, 512-block_len);
- /* write back link array */
- err = image_write_block(&l2_img->l1_img, cur_block, buf.raw);
- if (err)
- return err;
- l2_img->u.mfs.ABlink_dirty[cur_block-2] = 0;
- }
-
- cur_byte += block_len;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_open
-
- Open the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (O): open directory file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_open(struct mac_l2_imgref *l2_img, const char *path, mfs_dirref *dirref)
-{
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_MFS);
-
- if (path[0])
- return IMGTOOLERR_PATHNOTFOUND;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- dirref->cur_block = 0;
- dirref->cur_offset = 0;
- err = image_read_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_read
-
- Read one entry of directory file
-
- dirref (I/O): open directory file reference
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_read(mfs_dirref *dirref, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
-
- if (dir_entry)
- *dir_entry = NULL;
-
- if (dirref->index == dirref->l2_img->u.mfs.dir_num_files)
- /* EOF */
- return IMGTOOLERR_SUCCESS;
-
- /* get cat entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset == 512) || ! (cur_dir_entry->flags & 0x80))
- {
- dirref->cur_block++;
- dirref->cur_offset = 0;
- if (dirref->cur_block > dirref->l2_img->u.mfs.dir_blk_len)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- }
-
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
-
- if ((dirref->cur_offset + cur_dir_entry_len) > 512)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* entry looks valid: set pointer to entry */
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
-
- /* update file count */
- dirref->index++;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_insert
-
- Add an entry in the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (I/O): open directory file reference
- filename (I): name of the file for which an entry is created (Mac string)
- dir_entry (O): set to point to the created entry: set to NULL if EOF or
- error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_insert(struct mac_l2_imgref *l2_img, mfs_dirref *dirref, const uint8_t *new_fname, mfs_dir_entry **dir_entry)
-{
- size_t new_dir_entry_len;
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- uint32_t cur_date;
- imgtoolerr_t err;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- new_dir_entry_len = offsetof(mfs_dir_entry, name) + new_fname[0] + 1;
-
- for (dirref->cur_block = 0; dirref->cur_block < dirref->l2_img->u.mfs.dir_blk_len; dirref->cur_block++)
- {
- /* read current block */
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- dirref->cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- { /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- /* update file index (useless, but can't harm) */
- dirref->index++;
- }
-
- if (new_dir_entry_len <= (/*512*/510 - dirref->cur_offset))
- {
- /*memcpy(cur_dir_entry, new_dir_entry, new_dir_entry_len);*/
- cur_dir_entry->flags = 0x80;
- cur_dir_entry->flVersNum = 0x00;
- memset(&cur_dir_entry->flFinderInfo, 0, sizeof(cur_dir_entry->flFinderInfo));
- set_UINT32BE(&cur_dir_entry->fileID, dirref->l2_img->nxtCNID++);
- set_UINT16BE(&cur_dir_entry->dataStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, 0);
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, 0);
- cur_date = mac_time_now();
- set_UINT32BE(&cur_dir_entry->createDate, cur_date);
- set_UINT32BE(&cur_dir_entry->modifyDate, cur_date);
- mac_strcpy(cur_dir_entry->name, new_fname);
-
- /* update offset in block */
- dirref->cur_offset += new_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- if (dirref->cur_offset < 512)
- /* mark remaining space as free record */
- dirref->block_buffer[dirref->cur_offset] = 0;
- /* write back directory */
- err = image_write_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- /* update file count */
- dirref->l2_img->u.mfs.dir_num_files++;
-
- /* update MDB (nxtCNID & dir_num_files fields) */
- err = mfs_update_mdb(dirref->l2_img);
- if (err)
- return err;
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-/*
- mfs_dir_update
-
- Update one entry of directory file
-
- fileref (I/O): open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref)
-{
- uint16_t cur_block;
- uint16_t cur_offset;
- uint8_t block_buffer[512];
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
- for (cur_block = 0; cur_block < fileref->l2_img->u.mfs.dir_blk_len; cur_block++)
- {
- /* read current block */
- err = image_read_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- while ((cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- {
- if (get_UINT32BE(cur_dir_entry->fileID) == fileref->fileID)
- { /* found it: update directory entry */
- switch (fileref->forkType)
- {
- case data_fork:
- set_UINT16BE(&cur_dir_entry->dataStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, fileref->pLen);
- break;
-
- case rsrc_fork:
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, fileref->pLen);
- break;
- }
- /* write back directory */
- err = image_write_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
- }
- /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- cur_offset = (cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- }
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-
-/*
- mfs_find_dir_entry
-
- Find a file in an MFS directory
-
- dirref (I/O): open directory file reference
- filename (I): file name (Mac string)
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_find_dir_entry(mfs_dirref *dirref, const mac_str255 filename, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
- if (dir_entry)
- *dir_entry = NULL;
-
- /* scan dir for file */
- while (1)
- {
- err = mfs_dir_read(dirref, &cur_dir_entry);
- if (err)
- return err;
- if (!cur_dir_entry)
- /* EOF */
- break;
- if ((! mac_stricmp(filename, cur_dir_entry->name)) && (cur_dir_entry->flVersNum == 0))
- { /* file found */
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_FILENOTFOUND;
-}
-
-/*
- mfs_lookup_path
-
- Resolve a file path for MFS volumes. This function should not be called
- directly: call mac_lookup_path instead.
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (I/O): on output, catalog info for this file extracted from the
- catalog file (may be NULL)
- If create_it is true, created info will first be set according to the
- data from cat_info
- create_it (I): true if entry should be created if not found
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* rapid check */
- if (strchr(fpath, ':'))
- return IMGTOOLERR_BADFILENAME;
-
- /* extract file name */
- c_to_mac_strncpy(filename, fpath, strlen(fpath));
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if ((err == IMGTOOLERR_FILENOTFOUND) && create_it)
- err = mfs_dir_insert(l2_img, &dirref, filename, &dir_entry);
- if (err)
- return err;
-
- mac_strcpy(filename, dir_entry->name);
-
- if (create_it && cat_info)
- {
- dir_entry->flFinderInfo = cat_info->flFinderInfo;
- dir_entry->flags = (dir_entry->flags & 0x80) | (cat_info->flags & 0x7f);
- set_UINT32BE(&dir_entry->createDate, cat_info->createDate);
- set_UINT32BE(&dir_entry->modifyDate, cat_info->modifyDate);
-
- /* write current directory block */
- err = image_write_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref.cur_block, dirref.block_buffer);
- if (err)
- return err;
- }
-
- if (cat_info)
- {
- cat_info->flFinderInfo = dir_entry->flFinderInfo;
- memset(&cat_info->flXFinderInfo, 0, sizeof(cat_info->flXFinderInfo));
- cat_info->flags = dir_entry->flags;
- cat_info->fileID = get_UINT32BE(dir_entry->fileID);
- cat_info->dataLogicalSize = get_UINT32BE(dir_entry->dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(dir_entry->dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(dir_entry->rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(dir_entry->createDate);
- cat_info->modifyDate = get_UINT32BE(dir_entry->modifyDate);
- cat_info->dataRecType = 0x200; /* hcrt_File */
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open_internal
-
- Open a file fork, given its directory entry. This function should not be
- called directly: call mfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- dir_entry (I): directory entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open_internal(struct mac_l2_imgref *l2_img, const mfs_dir_entry *dir_entry, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_MFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(dir_entry->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->dataStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->dataLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->dataPhysicalSize);
- break;
-
- case rsrc_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->rsrcStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open
-
- Open a file located on a MFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if (err)
- return err;
-
- /* open it */
- return mfs_file_open_internal(l2_img, dir_entry, fork, fileref);
-}
-
-/*
- mfs_get_ABlink
-
- Read one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
-
- Returns the 12-bit value read in array.
-*/
-static uint16_t mfs_get_ABlink(struct mac_l2_imgref *l2_img, uint16_t AB_address)
-{
- uint16_t reply;
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- reply = (l2_img->u.mfs.ABlink[base] << 4) | ((l2_img->u.mfs.ABlink[base+1] >> 4) & 0x0f);
- else
- reply = ((l2_img->u.mfs.ABlink[base+1] << 8) & 0xf00) | l2_img->u.mfs.ABlink[base+2];
-
- return reply;
-}
-
-/*
- mfs_set_ABlink
-
- Set one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
- data (I): 12-bit value to write in array
-*/
-static void mfs_set_ABlink(struct mac_l2_imgref *l2_img, uint16_t AB_address, uint16_t data)
-{
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- {
- l2_img->u.mfs.ABlink[base] = (data >> 4) & 0xff;
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0x0f) | ((data << 4) & 0xf0);
-
- l2_img->u.mfs.ABlink_dirty[(base+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- }
- else
- {
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0xf0) | ((data >> 8) & 0x0f);
- l2_img->u.mfs.ABlink[base+2] = data & 0xff;
-
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+2+64)/512] = 1;
- }
-}
-
-/*
- mfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address)
-{
- uint32_t AB_num;
- uint32_t i;
- uint16_t AB_address;
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
-
- AB_address = fileref->mfs.stBlk;
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- for (i=0; i<AB_num; i++)
- {
- AB_address = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- }
-
- *block_address = fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_allocABs
-
- Allocate a chunk of ABs
-
- fileref (I/O): open mac file reference
- lastAB (I): AB address on disk of last file AB (only if
- fileref->mfs.stBlk != 1)
- allocABs (I): number of ABs to allocate in addition to the current file
- allocation
- fblock (I): first file block to allocate (used for tag data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_allocABs(struct mac_fileref *fileref, uint16_t lastAB, uint32_t allocABs, uint32_t fblock)
-{
- int numABs = fileref->l2_img->numABs;
- int free_ABs;
- int i, j;
- floppy_tag_record tag;
- int extentBaseAB, extentABlen;
- int firstBestExtentBaseAB = 0, firstBestExtentABlen;
- int secondBestExtentBaseAB = 0, secondBestExtentABlen;
- imgtoolerr_t err;
-
- /* return if done */
- if (! allocABs)
- return IMGTOOLERR_SUCCESS;
-
- /* compute free space */
- free_ABs = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block;
- }
- }
- }
- }
-
- free_ABs++;
- }
-corrupt_free_block:
- ;
- }
-
- /* check we have enough free space */
- if (free_ABs < allocABs)
- return IMGTOOLERR_NOSPACE;
-
- if (fileref->mfs.stBlk != 1)
- { /* try to extend last file extent */
- /* append free ABs after last AB */
- for (i=lastAB+1; (mfs_get_ABlink(fileref->l2_img, i) == 0) && (allocABs > 0) && (i < numABs); i++)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block2;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, lastAB, i+2);
- lastAB = i;
- allocABs--;
- free_ABs--;
- }
-corrupt_free_block2:
- /* return if done */
- if (! allocABs)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return IMGTOOLERR_SUCCESS; /* done */
- }
- }
-
- while (allocABs)
- {
- /* find smallest data block at least nb_alloc_physrecs in length, and largest data block less than nb_alloc_physrecs in length */
- firstBestExtentABlen = INT_MAX;
- secondBestExtentABlen = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- { /* found one free block */
- /* compute its length */
- extentBaseAB = i;
- extentABlen = 0;
- while ((i<numABs) && (mfs_get_ABlink(fileref->l2_img, i) == 0))
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block3;
- }
- }
- }
- }
-
- extentABlen++;
- i++;
- }
-corrupt_free_block3:
- /* compare to previous best and second-best blocks */
- if ((extentABlen < firstBestExtentABlen) && (extentABlen >= allocABs))
- {
- firstBestExtentBaseAB = extentBaseAB;
- firstBestExtentABlen = extentABlen;
- if (extentABlen == allocABs)
- /* no need to search further */
- break;
- }
- else if ((extentABlen > secondBestExtentABlen) && (extentABlen < allocABs))
- {
- secondBestExtentBaseAB = extentBaseAB;
- secondBestExtentABlen = extentABlen;
- }
- }
- }
-
- if (firstBestExtentABlen != INT_MAX)
- { /* found one contiguous block which can hold it all */
- extentABlen = allocABs;
- for (i=0; i<allocABs; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, firstBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = firstBestExtentBaseAB+i+2;
- lastAB = firstBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs = 0;
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- /*return IMGTOOLERR_SUCCESS;*/ /* done */
- }
- else if (secondBestExtentABlen != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- for (i=0; i<secondBestExtentABlen; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, secondBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = secondBestExtentBaseAB+i+2;
- lastAB = secondBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs -= secondBestExtentABlen;
- }
- else
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_setABeof
-
- Set physical file EOF in ABs
-
- fileref (I/O): open mac file reference
- newABeof (I): desired number of allocated ABs for this file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, uint32_t newABeof)
-{
- uint16_t AB_address = 0;
- uint16_t AB_link;
- int i, j;
- floppy_tag_record tag;
- int MDB_dirty = 0;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- /* run through link chain until we reach the old or the new EOF */
- AB_link = fileref->mfs.stBlk;
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- for (i=0; (i<newABeof) && (AB_link!=1); i++)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- }
-
- if (i == newABeof)
- { /* new EOF is shorter than old one */
- /* mark new eof */
- if (i==0)
- fileref->mfs.stBlk = 1;
- else
- {
- mfs_set_ABlink(fileref->l2_img, AB_address, 1);
- MDB_dirty = 1;
- }
-
- /* free all remaining blocks */
- while (AB_link != 1)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- { /* 0 -> empty block: there is no way an empty block could make
- it into the link chain!!! */
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, AB_address, 0);
- fileref->l2_img->freeABs++;
- MDB_dirty = 1;
- /* set tag to free */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- memset(&tag, 0, sizeof(tag));
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
- }
- }
- i++;
- }
- }
- else
- { /* new EOF is larger than old one */
- err = mfs_file_allocABs(fileref, AB_address, newABeof - i, i * fileref->l2_img->blocksperAB);
- if (err)
- return err;
- MDB_dirty = 1;
- }
-
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
-
- fileref->pLen = newABeof * (fileref->l2_img->blocksperAB * 512);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mfs_hashString
-
- Hash a string: under MFS, this provides the resource ID of the comment
- resource associated with the file whose name is provided (FCMT resource
- type).
-
- Ripped from Apple technote TB06 (converted from 68k ASM to C)
-
- string (I): string to hash
-
- Returns hash value
-*/
-static int mfs_hashString(const mac_str255 string)
-{
- int reply;
- int len;
- int i;
-
- len = string[0];
-
- reply = 0;
- for (i=0; i<len; i++)
- {
- reply ^= string[i+1];
- if (reply & 1)
- reply = ((reply >> 1) & 0x7fff) | ~0x7fff;
- else
- reply = ((reply >> 1) & 0x7fff);
- if (! (reply & 0x8000))
- reply = - reply;
- }
-
- return reply;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark HFS IMPLEMENTATION
-#endif
-
-/*
- HFS extents B-tree key
-*/
-struct hfs_extentKey
-{
- uint8_t keyLength; /* length of key, excluding this field */
- uint8_t forkType; /* 0 = data fork, FF = resource fork */
- UINT32BE fileID; /* file ID */
- UINT16BE startBlock; /* first file allocation block number in this extent */
-};
-enum
-{
- keyLength_hfs_extentKey = sizeof(hfs_extentKey) - sizeof(uint8_t)
-};
-
-/*
- HFS catalog B-tree key
-*/
-struct hfs_catKey
-{
- uint8_t keyLen; /* key length */
- uint8_t resrv1; /* reserved */
- UINT32BE parID; /* parent directory ID */
- mac_str31 cName; /* catalog node name */
- /* note that in index nodes, it is a mac_str31, but
- in leaf keys it's a variable-length string */
-};
-
-/*
- HFS catalog data record for a folder - 70 bytes
-*/
-struct hfs_catFolderData
-{
- UINT16BE recordType; /* record type */
- UINT16BE flags; /* folder flags */
- UINT16BE valence; /* folder valence */
- UINT32BE folderID; /* folder ID */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_DInfo userInfo; /* Finder information */
- mac_DXInfo finderInfo; /* additional Finder information */
- UINT32BE reserved[4]; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a file - 102 bytes
-*/
-struct hfs_catFileData
-{
- UINT16BE recordType; /* record type */
- uint8_t flags; /* file flags */
- uint8_t fileType; /* file type (reserved, always 0?) */
- mac_FInfo userInfo; /* Finder information */
- UINT32BE fileID; /* file ID */
- UINT16BE dataStartBlock; /* not used - set to zero */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* not used - set to zero */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_FXInfo finderInfo; /* additional Finder information */
- UINT16BE clumpSize; /* file clump size (not used) */
- hfs_extent_3 dataExtents; /* first data fork extent record */
- hfs_extent_3 rsrcExtents; /* first resource fork extent record */
- UINT32BE reserved; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a thread - 46 bytes
-
- The key for a thread record features the CNID of the item and an empty
- name, instead of the CNID of the parent and the item name.
-*/
-struct hfs_catThreadData
-{
- UINT16BE recordType; /* record type */
- UINT32BE reserved[2]; /* reserved - set to zero */
- UINT32BE parID; /* parent ID for this catalog node */
- mac_str31 nodeName; /* name of this catalog node */
-};
-
-/*
- union for all types at once
-*/
-union hfs_catData
-{
- UINT16BE dataType;
- hfs_catFolderData folder;
- hfs_catFileData file;
- hfs_catThreadData thread;
-};
-
-/*
- HFS catalog record types
-*/
-enum
-{
- hcrt_Folder = 0x0100, /* Folder record */
- hcrt_File = 0x0200, /* File record */
- hcrt_FolderThread = 0x0300, /* Folder thread record */
- hcrt_FileThread = 0x0400 /* File thread record */
-};
-
-/*
- Catalog file record flags
-
- This is similar to the MFS catalog flag field, but the "thread exists" flag
- (0x02) is specific to HFS/HFS+, whereas the "Record in use" flag (0x80) is
- only used by MFS.
-*/
-enum
-{
- cfrf_fileLocked = 0x01, /* file is locked and cannot be written to */
- cfrf_threadExists = 0x02 /* a file thread record exists for this file */
-};
-
-/*
- BT functions used by HFS functions
-*/
-struct BT_leaf_rec_enumerator
-{
- mac_BTref *BTref;
- uint32_t cur_node;
- int cur_rec;
-};
-
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent);
-static void BT_close(mac_BTref *BTref);
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- uint32_t *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found);
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len);
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator);
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len);
-
-struct hfs_cat_enumerator
-{
- struct mac_l2_imgref *l2_img;
- BT_leaf_rec_enumerator BT_enumerator;
- uint32_t parID;
-};
-
-/*
- hfs_open_extents_file
-
- Open the file extents B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_extents_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 3;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->xtFlSize);
- memcpy(fileref->hfs.extents, mdb->xtExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_open_cat_file
-
- Open the disk catalog B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_cat_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 4;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->ctFlSize);
- memcpy(fileref->hfs.extents, mdb->ctExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_extentKey_compare
-
- key compare function for file extents B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_extentKey_compare(const void *p1, const void *p2)
-{
- const hfs_extentKey *key1 = (const hfs_extentKey*)p1;
- const hfs_extentKey *key2 = (const hfs_extentKey*)p2;
-
- /* let's keep it simple for now */
- return memcmp(key1, key2, sizeof(hfs_extentKey));
-}
-
-/*
- hfs_catKey_compare
-
- key compare function for disk catalog B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_catKey_compare(const void *p1, const void *p2)
-{
- const hfs_catKey *key1 = (const hfs_catKey *)p1;
- const hfs_catKey *key2 = (const hfs_catKey *)p2;
-
- if (get_UINT32BE(key1->parID) != get_UINT32BE(key2->parID))
- return (get_UINT32BE(key1->parID) < get_UINT32BE(key2->parID)) ? -1 : +1;
-
- return mac_stricmp(key1->cName, key2->cName);
-}
-
-/*
- hfs_image_open
-
- Open a HFS image. Image must already be open on level 1.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_image_open(imgtool::image &image, imgtool::stream::ptr &&stream)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = &image;
- l2_img->l1_img.heads = 2;
- l2_img->format = L2I_HFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->hfs_mdb.sigWord[0] != 0x42) || (buf->hfs_mdb.sigWord[1] != 0x44)
- || (buf->hfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.hfs.VBM_start = get_UINT16BE(buf->hfs_mdb.VBMSt);
-
- l2_img->numABs = get_UINT16BE(buf->hfs_mdb.nmAlBlks);
- if (get_UINT32BE(buf->hfs_mdb.alBlkSiz) % 512)
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->hfs_mdb.alBlkSiz) / 512;
- l2_img->u.hfs.ABStart = get_UINT16BE(buf->hfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->hfs_mdb.nxtCNID);
-
- l2_img->freeABs = get_UINT16BE(buf->hfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.hfs.volname, buf->hfs_mdb.VN);
-
- /* open extents and catalog BT */
- err = hfs_open_extents_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.extents_BT.fileref);
- if (err)
- return err;
- err = BT_open(&l2_img->u.hfs.extents_BT, hfs_extentKey_compare, true);
- if (err)
- return err;
- if ((l2_img->u.hfs.extents_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.extents_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.extents_BT.maxKeyLength != 7))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- err = hfs_open_cat_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.cat_BT.fileref);
- if (err)
- {
- BT_close(&l2_img->u.hfs.extents_BT);
- return err;
- }
- err = BT_open(&l2_img->u.hfs.cat_BT, hfs_catKey_compare, false);
- if (err)
- {
- return err;
- }
- if ((l2_img->u.hfs.cat_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.cat_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.cat_BT.maxKeyLength != 37))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* extract volume bitmap */
- {
- int byte_len = (l2_img->numABs + 7) / 8;
- int cur_byte = 0;
- int cur_block = l2_img->u.hfs.VBM_start;
-
- while (cur_byte < byte_len)
- {
- /* read next block */
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- cur_block++;
-
- /* append this block to VBM */
- memcpy(l2_img->u.hfs.VBM+cur_byte, buf->raw, 512);
- cur_byte += 512;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- hfs_image_close
-
- Close a HFS image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void hfs_image_close(struct mac_l2_imgref *l2_img)
-{
- assert(l2_img->format == L2I_HFS);
-
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
-}
-#endif
-
-/*
- hfs_get_cat_record_data
-
- extract data from a catalog B-tree leaf record
-
- l2_img (I/O): level-2 image reference
- rec_raw (I): pointer to record key and data, as returned by
- BT_node_get_keyed_record
- rec_len (I): total length of record, as returned by
- BT_node_get_keyed_record
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_get_cat_record_data(struct mac_l2_imgref *l2_img, void *rec_raw, int rec_len, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey *lrec_key;
- void *rec_data_raw;
- hfs_catData *lrec_data;
- int rec_data_len;
- int min_data_size;
- imgtoolerr_t err;
-
-
- assert(l2_img->format == L2I_HFS);
-
- lrec_key = (hfs_catKey*)rec_raw;
- /* check that key is long enough to hold it all */
- if ((lrec_key->keyLen+1) < (offsetof(hfs_catKey, cName) + lrec_key->cName[0] + 1))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get pointer to record data */
- err = BT_get_keyed_record_data(&l2_img->u.hfs.cat_BT, rec_raw, rec_len, &rec_data_raw, &rec_data_len);
- if (err)
- return err;
- lrec_data = (hfs_catData*)rec_data_raw;
-
- /* extract record type */
- if (rec_data_len < 2)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* check that the record is large enough for its type */
- switch (get_UINT16BE(lrec_data->dataType))
- {
- case hcrt_Folder:
- min_data_size = sizeof(hfs_catFolderData);
- break;
-
- case hcrt_File:
- min_data_size = sizeof(hfs_catFileData);
- break;
-
- case hcrt_FolderThread:
- case hcrt_FileThread:
- min_data_size = sizeof(hfs_catThreadData);
- break;
-
- default:
- /* records of unknown type can be safely ignored */
- min_data_size = 0;
- break;
- }
-
- if (rec_data_len < min_data_size)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_key)
- *rec_key = lrec_key;
- if (rec_data)
- *rec_data = lrec_data;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_open
-
- Open an enumerator on the disk catalog
-
- l2_img (I/O): level-2 image reference
- enumerator (O): open catalog enumerator reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_open(struct mac_l2_imgref *l2_img, const char *path, hfs_cat_enumerator *enumerator)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
-
- assert(l2_img->format == L2I_HFS);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(l2_img, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_Folder)
- return IMGTOOLERR_FILENOTFOUND;
-
- enumerator->l2_img = l2_img;
- enumerator->parID = parID;
-
- return BT_leaf_rec_enumerator_open(&l2_img->u.hfs.cat_BT, &enumerator->BT_enumerator);
-}
-
-/*
- hfs_cat_read
-
- Enumerate the disk catalog
-
- enumerator (I/O): open catalog enumerator reference
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_read(hfs_cat_enumerator *enumerator, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- void *rec;
- int rec_len = 0;
- imgtoolerr_t err;
-
-
- *rec_key = NULL;
- *rec_data = NULL;
-
- /* read next record */
- err = BT_leaf_rec_enumerator_read(&enumerator->BT_enumerator, &rec, &rec_len);
- if (err)
- return err;
-
- /* check EOList condition */
- if (rec == NULL)
- return IMGTOOLERR_SUCCESS;
-
- /* extract record data */
- err = hfs_get_cat_record_data(enumerator->l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_search
-
- Search the catalog for a given file
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- cName (I): file name
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_search(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str31 cName, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey search_key;
- void *rec;
- int rec_len;
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_HFS);
-
- if (cName[0] > 31)
- return IMGTOOLERR_UNEXPECTED;
-
- /* generate search key */
- search_key.keyLen = search_key.resrv1 = 0; /* these fields do not matter
- to the compare function, so we
- don't fill them */
- set_UINT32BE(&search_key.parID, parID);
- mac_strcpy(search_key.cName, cName);
-
- /* search key */
- err = BT_search_leaf_rec(&l2_img->u.hfs.cat_BT, &search_key, NULL, NULL, &rec, &rec_len, true, NULL);
- if (err)
- return err;
-
- /* extract record data */
- err = hfs_get_cat_record_data(l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_lookup_path
-
- Resolve a file path
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the file parent directory
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info)
-{
- const char *element_start;
- int element_len;
- mac_str255 mac_element_name;
- //int level;
- imgtoolerr_t err;
- hfs_catKey *catrec_key = NULL;
- hfs_catData *catrec_data = NULL;
- uint16_t dataRecType = hcrt_Folder;
-
- /* iterate each path element */
- element_start = fpath;
- //level = 0;
- *parID = 2; /* root parID is 2 */
-
- while(*element_start)
- {
- /* find next path element */
- element_len = strlen(element_start);
- /* decode path element name */
- c_to_mac_strncpy(mac_element_name, element_start, element_len);
-
- err = hfs_cat_search(l2_img, *parID, mac_element_name, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* regular folder/file name */
- if (dataRecType == hcrt_Folder)
- *parID = get_UINT32BE(catrec_data->folder.folderID);
- else if (element_start[element_len + 1])
- return IMGTOOLERR_BADFILENAME;
-
- /* iterate */
- element_start += element_len + 1;
- }
-
- if (catrec_key && (dataRecType == hcrt_File))
- {
- /* save ref */
- *parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(filename, catrec_key->cName);
- }
-
- if (cat_info)
- {
- if (catrec_data && (dataRecType == hcrt_File))
- {
- cat_info->flFinderInfo = catrec_data->file.userInfo;
- cat_info->flXFinderInfo = catrec_data->file.finderInfo;
- cat_info->flags = catrec_data->file.flags;
- cat_info->fileID = get_UINT32BE(catrec_data->file.fileID);
- cat_info->dataLogicalSize = get_UINT32BE(catrec_data->file.dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(catrec_data->file.dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(catrec_data->file.rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(catrec_data->file.createDate);
- cat_info->modifyDate = get_UINT32BE(catrec_data->file.modifyDate);
- }
- else
- {
- memset(cat_info, 0, sizeof(*cat_info));
- }
- cat_info->dataRecType = dataRecType;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open_internal
-
- Open a file fork, given its catalog entry. This function should not be
- called directly: call hfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- file_rec (I): catalog entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open_internal(struct mac_l2_imgref *l2_img, const hfs_catFileData *file_rec, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(file_rec->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->eof = get_UINT32BE(file_rec->dataLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->dataPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->dataExtents, sizeof(hfs_extent_3));
- break;
-
- case rsrc_fork:
- fileref->eof = get_UINT32BE(file_rec->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->rsrcPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->rsrcExtents, sizeof(hfs_extent_3));
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open
-
- Open a file located on a HFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- uint16_t dataRecType;
- imgtoolerr_t err;
-
- /* lookup file in catalog */
- err = hfs_cat_search(l2_img, parID, filename, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* file expected */
- if (dataRecType != hcrt_File)
- return IMGTOOLERR_BADFILENAME;
-
- fileref->hfs.parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(fileref->hfs.filename, catrec_key->cName);
-
- /* open it */
- return hfs_file_open_internal(l2_img, &catrec_data->file, fork, fileref);
-}
-
-/*
- hfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address)
-{
- uint32_t AB_num;
- uint32_t cur_AB;
- uint32_t i;
- void *cur_extents_raw;
- hfs_extent *cur_extents;
- int cur_extents_len;
- void *extents_BT_rec;
- int extents_BT_rec_len;
- imgtoolerr_t err;
- uint16_t AB_address;
-
- assert(fileref->l2_img->format == L2I_HFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
- cur_AB = 0;
- cur_extents = fileref->hfs.extents;
-
- /* first look in catalog tree extents */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- {
- /* extent not found: read extents record from extents BT */
- hfs_extentKey search_key;
- hfs_extentKey *found_key;
-
- search_key.keyLength = keyLength_hfs_extentKey;
- search_key.forkType = fileref->forkType;
- set_UINT32BE(&search_key.fileID, fileref->fileID);
- set_UINT16BE(&search_key.startBlock, AB_num);
-
- /* search for the record with the largest key lower than or equal to
- search_key. The keys are constructed in such a way that, if a record
- includes AB_num, it is that one. */
- err = BT_search_leaf_rec(&fileref->l2_img->u.hfs.extents_BT, &search_key,
- NULL, NULL, &extents_BT_rec, &extents_BT_rec_len,
- false, NULL);
- if (err)
- return err;
-
- if (extents_BT_rec == NULL)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- found_key = (hfs_extentKey*)extents_BT_rec;
- /* check that this record concerns the correct file */
- if ((found_key->forkType != fileref->forkType)
- || (get_UINT32BE(found_key->fileID) != fileref->fileID))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract start AB */
- cur_AB = get_UINT16BE(found_key->startBlock);
- /* get extents pointer */
- err = BT_get_keyed_record_data(&fileref->l2_img->u.hfs.extents_BT, extents_BT_rec, extents_BT_rec_len, &cur_extents_raw, &cur_extents_len);
- if (err)
- return err;
- if (cur_extents_len < 3*sizeof(hfs_extent))
- return IMGTOOLERR_CORRUPTIMAGE;
- cur_extents = (hfs_extent*)cur_extents_raw;
-
- /* pick correct extent in record */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- /* extent not found */
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- AB_address = get_UINT16BE(cur_extents[i].stABN) + (AB_num-cur_AB);
-
- if (AB_address >= fileref->l2_img->numABs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *block_address = fileref->l2_img->u.hfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark B-TREE IMPLEMENTATION
-#endif
-
-/*
- B-tree (Balanced search tree) files are used by the HFS and HFS+ file
- systems: the Extents and Catalog files are both B-Tree.
-
- Note that these B-trees are B+-trees: data is only on the leaf level, and
- nodes located on the same level are also linked sequentially, which allows
- fast sequenctial access to the catalog file.
-
- These files are normal files, except for the fact that they are not
- referenced from the catalog but the MDB. They are allocated in fixed-size
- records of 512 bytes (HFS). (HFS+ supports any power of two from 512
- through 32768, and uses a default of 1024 for Extents, and 4096 for both
- Catalog and Attributes.)
-
- Nodes can contain any number of records. The nodes can be of any of four
- types: header node (unique node with b-tree information, pointer to root
- node and start of the node allocation bitmap), map nodes (which are created
- when the node allocation bitmap outgrows the header node), index nodes
- (root and branch node that enable to efficiently search the leaf nodes for
- a specific key value), and leaf nodes (which hold the actual user data
- records with keys and data). The first node is always a header node.
- Other nodes can be of any of the 3 other type, or they can be free.
-*/
-
-/*
- BTNodeHeader
-
- Header of a node record
-*/
-struct BTNodeHeader
-{
- UINT32BE fLink; /* (index of) next node at this level */
- UINT32BE bLink; /* (index of) previous node at this level */
- uint8_t kind; /* kind of node (leaf, index, header, map) */
- uint8_t height; /* zero for header, map; 1 for leaf, 2 through
- treeDepth for index (child is one LESS than
- parent, whatever IM says) */
- UINT16BE numRecords; /* number of records in this node */
- UINT16BE reserved; /* reserved; set to zero */
-};
-
-/*
- Constants for BTNodeHeader kind field
-*/
-enum
-{
- btnk_leafNode = 0xff, /* leaf nodes hold the actual user data records
- with keys and data */
- btnk_indexNode = 0, /* root and branch node that enable to efficiently
- search the leaf nodes for a specific key value */
- btnk_headerNode = 1, /* unique node with b-tree information, pointer to
- root node and start of the node allocation
- bitmap */
- btnk_mapNode = 2 /* map nodes are created when the node allocation
- bitmap outgrows the header node */
-};
-
-/*
- BTHeaderRecord: first record of a B-tree header node (second record is
- unused, and third is node allocation bitmap).
-*/
-struct BTHeaderRecord
-{
- UINT16BE treeDepth; /* maximum height (usually leaf nodes) */
- UINT32BE rootNode; /* node number of root node */
- UINT32BE leafRecords; /* number of leaf records in all leaf nodes */
- UINT32BE firstLeafNode; /* node number of first leaf node */
- UINT32BE lastLeafNode; /* node number of last leaf node */
- UINT16BE nodeSize; /* size of a node, in bytes */
- UINT16BE maxKeyLength; /* maximum length of data (index + leaf) record keys;
- length of all index record keys if
- btha_variableIndexKeysMask attribute flag is not set */
- UINT32BE totalNodes; /* total number of nodes in tree */
- UINT32BE freeNodes; /* number of unused (free) nodes in tree */
-
- UINT16BE reserved1; /* unused */
- UINT32BE clumpSize; /* used in some HFS implementations? (reserved in
- early HFS implementations, and in HFS Plus) */
- uint8_t btreeType; /* reserved - set to 0 */
- uint8_t reserved2; /* reserved */
- UINT32BE attributes; /* persistent attributes about the tree */
- UINT32BE reserved3[16]; /* reserved */
-};
-
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent);
-
-/*
- BT_open
-
- Open a file as a B-tree. The file must be already open as a macintosh
- file.
-
- BTref (I/O): B-tree file handle to open (BTref->fileref must have been
- open previously)
- key_compare_func (I): function that compares two keys
- is_extent (I): true if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent)
-{
- imgtoolerr_t err;
- BTNodeHeader node_header;
- BTHeaderRecord header_rec;
-
- /* seek to node 0 */
- err = mac_file_seek(&BTref->fileref, 0);
- if (err)
- return err;
-
- /* read node header */
- err = mac_file_read(&BTref->fileref, sizeof(node_header), &node_header);
- if (err)
- return err;
-
- if ((node_header.kind != btnk_headerNode) || (get_UINT16BE(node_header.numRecords) < 3)
- || (node_header.height != 0))
- return IMGTOOLERR_CORRUPTIMAGE; /* right??? */
-
- /* CHEESY HACK: we assume that the header record immediately follows the
- node header. This is because we need to know the node length to know where
- the record pointers are located, but we need to read the header record to
- know the node length. */
- err = mac_file_read(&BTref->fileref, sizeof(header_rec), &header_rec);
- if (err)
- return err;
-
- BTref->nodeSize = get_UINT16BE(header_rec.nodeSize);
- BTref->rootNode = get_UINT32BE(header_rec.rootNode);
- BTref->firstLeafNode = get_UINT32BE(header_rec.firstLeafNode);
- BTref->attributes = get_UINT32BE(header_rec.attributes);
- BTref->treeDepth = get_UINT16BE(header_rec.treeDepth);
- BTref->maxKeyLength = get_UINT16BE(header_rec.maxKeyLength);
-
- BTref->key_compare_func = key_compare_func;
-
- BTref->node_buf = malloc(BTref->nodeSize);
- if (!BTref->node_buf)
- return IMGTOOLERR_OUTOFMEMORY;
-
- if (BTREE_CHECKS)
- {
- /* optional: check integrity of B-tree */
- err = BT_check(BTref, is_extent);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_close
-
- Close a B-tree
-
- BTref (I/O): open B-tree file handle
-*/
-static void BT_close(mac_BTref *BTref)
-{
- free(BTref->node_buf);
-}
-
-/*
- BT_read_node
-
- Read a node from a B-tree
-
- BTref (I/O): open B-tree file handle
- node_ID (I): index of the node to read
- expected_kind (I): kind of the node to read
- expected_depth (I): depth of the node to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_read_node(mac_BTref *BTref, uint32_t node_ID, int expected_kind, int expected_depth, void *dest)
-{
- imgtoolerr_t err;
-
- /* seek to node */
- err = mac_file_seek(&BTref->fileref, node_ID*BTref->nodeSize);
- if (err)
- return err;
-
- /* read it */
- err = mac_file_read(&BTref->fileref, BTref->nodeSize, dest);
- if (err)
- return err;
-
- /* check node kind and depth */
- if ((((BTNodeHeader *) dest)->kind != expected_kind)
- || (((BTNodeHeader *) dest)->height != expected_depth))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_record
-
- Extract a raw record from a B-tree node
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_record(mac_BTref *BTref, void *node_buf, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- uint16_t node_numRecords = get_UINT16BE(((BTNodeHeader *) node_buf)->numRecords);
- uint16_t offset;
- uint16_t next_offset;
-
- if (recnum >= node_numRecords)
- return IMGTOOLERR_UNEXPECTED;
-
- int recnum_s = (int)recnum;
- offset = get_UINT16BE(((UINT16BE *)((uint8_t *) node_buf + BTref->nodeSize))[-recnum_s - 1]);
- next_offset = get_UINT16BE(((UINT16BE *)((uint8_t *) node_buf + BTref->nodeSize))[-recnum_s - 2]);
-
- if ((offset < sizeof(BTNodeHeader)) || (offset > BTref->nodeSize-2*node_numRecords)
- || (next_offset < sizeof(BTNodeHeader)) || (next_offset > BTref->nodeSize-2*node_numRecords)
- || (offset & 1) || (next_offset & 1)
- || (offset > next_offset))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *rec_ptr = (uint8_t *)node_buf + offset;
- *rec_len = next_offset - offset;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_keyed_record
-
- Extract a keyed record from a B-tree node. Equivalent to
- BT_node_get_record, only we do extra checks.
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- node_is_index (I): true if node is index node
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_keyed_record(mac_BTref *BTref, void *node_buf, int node_is_index, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- imgtoolerr_t err;
- void *lrec_ptr;
- int lrec_len;
- int key_len;
-
- /* extract record */
- err = BT_node_get_record(BTref, node_buf, recnum, &lrec_ptr, &lrec_len);
- if (err)
- return err;
-
- /* read key len */
- key_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)lrec_ptr)
- : (* (uint8_t *)lrec_ptr);
-
- /* check that key fits in record */
- if ((key_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1)) > lrec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (key_len > BTref->maxKeyLength)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (node_is_index && (! (BTref->attributes & btha_variableIndexKeysMask)) && (key_len != BTref->maxKeyLength))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_ptr)
- *rec_ptr = lrec_ptr;
- if (rec_len)
- *rec_len = lrec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_get_keyed_record_data
-
- extract data from a keyed record
-
- BTref (I/O): open B-tree file handle
- rec_ptr (I): point to start of record (key + data)
- rec_len (I): total length of record (key + data)
- data_ptr (O): set to point to record data
- data_len (O): set to length of record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len)
-{
- int lkey_len;
- int data_offset;
-
- /* read key len */
- lkey_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)rec_ptr)
- : (* (uint8_t *)rec_ptr);
-
- /* compute offset to data record */
- data_offset = lkey_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1);
- if (data_offset > rec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
- /* fix alignment */
- if (data_offset & 1)
- data_offset++;
-
- if (data_ptr)
- *data_ptr = (uint8_t *)rec_ptr + data_offset;
- if (data_len)
- *data_len = (rec_len > data_offset) ? rec_len-data_offset : 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_check
-
- Check integrity of a complete B-tree
-
- BTref (I/O): open B-tree file handle
- is_extent (I): true if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-struct data_nodes_t
-{
- void *buf;
- uint32_t node_num;
- uint32_t cur_rec;
- uint32_t num_recs;
-};
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent)
-{
- uint16_t node_numRecords;
- BTHeaderRecord *header_rec;
- uint8_t *bitmap;
-
- data_nodes_t *data_nodes;
- int i, j;
- uint32_t cur_node, prev_node;
- void *rec1, *rec2;
- int rec1_len, rec2_len;
- void *rec1_data;
- int rec1_data_len;
- uint32_t totalNodes, lastLeafNode;
- uint32_t freeNodes;
- int compare_result;
- uint32_t map_count, map_len;
- uint32_t run_len;
- uint32_t run_bit_len;
- uint32_t actualFreeNodes;
- imgtoolerr_t err;
- uint32_t maxExtentAB = 0, maxExtentNode = 0, extentEOL = 0; /* if is_extent is true */
-
- if (is_extent)
- {
- switch (BTref->fileref.l2_img->format)
- {
- case L2I_MFS:
- /* MFS does not feature any extents B-tree! */
- return IMGTOOLERR_UNEXPECTED;
-
- case L2I_HFS:
- maxExtentAB = 0;
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(BTref->fileref.hfs.extents[j].numABlks);
- maxExtentNode = (uint64_t)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- extentEOL = false;
- break;
- }
- }
-
- /* read header node */
- if ((! is_extent) || (0 < maxExtentNode))
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- return err;
-
- /* check we have enough records */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- if (node_numRecords < 3)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get header record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- return err;
- header_rec = (BTHeaderRecord *)rec1;
-
- /* check length of header record */
- if (rec1_len < sizeof(BTHeaderRecord))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- totalNodes = get_UINT32BE(header_rec->totalNodes);
- if (totalNodes == 0)
- /* we need at least one header node */
- return IMGTOOLERR_CORRUPTIMAGE;
- lastLeafNode = get_UINT32BE(header_rec->lastLeafNode);
- freeNodes = get_UINT32BE(header_rec->freeNodes);
-
- /* check file length */
- if ((BTref->nodeSize * totalNodes) > BTref->fileref.pLen)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* initialize for the function postlog ("bail:" tag) */
- err = IMGTOOLERR_SUCCESS;
- bitmap = NULL;
- data_nodes = NULL;
-
- /* alloc buffer for reconstructed bitmap */
- map_len = (totalNodes + 7) / 8;
- bitmap = (uint8_t*)malloc(map_len);
- if (! bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(bitmap, 0, map_len);
-
- /* check B-tree data nodes (i.e. index and leaf nodes) */
- if (BTref->treeDepth == 0)
- {
- /* B-tree is empty */
- if (BTref->rootNode || BTref->firstLeafNode || lastLeafNode)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
- else
- {
- /* alloc array of buffers for catalog data nodes */
- data_nodes = (data_nodes_t *)malloc(sizeof(data_nodes_t) * BTref->treeDepth);
- if (! data_nodes)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- for (i=0; i<BTref->treeDepth; i++)
- data_nodes[i].buf = NULL; /* required for function postlog to work should next loop fail */
- for (i=0; i<BTref->treeDepth; i++)
- {
- data_nodes[i].buf = malloc(BTref->nodeSize);
- if (!data_nodes[i].buf)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
-
- /* read first data nodes */
- cur_node = BTref->rootNode;
- for (i=BTref->treeDepth-1; i>=0; i--)
- {
- /* check node index */
- if (cur_node >= totalNodes)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks
- that forward and back linking match and that node height is correct
- are enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that it is the first node at this level */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level if applicable */
- if (i != 0)
- {
- /* extract first record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, true, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
- }
- }
-
- /* check that a) the root node has no successor, and b) that we have really
- read the first leaf node */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[BTref->treeDepth-1].buf)->fLink)
- || (cur_node != BTref->firstLeafNode))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* check that keys are ordered correctly */
- while (1)
- {
- /* iterate through parent nodes */
- i = 0;
- while ((i<BTref->treeDepth) && ((data_nodes[i].cur_rec == 0) || (data_nodes[i].cur_rec == data_nodes[i].num_recs)))
- {
- /* read next node if necessary */
- if (data_nodes[i].cur_rec == data_nodes[i].num_recs)
- {
- /* get link to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink);
- if (cur_node == 0)
- {
- if (i == 0)
- /* normal End of List */
- goto end_of_list;
- else
- {
- /* error */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that backward linking match forward linking */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink) != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* next test is not necessary because we have checked that
- the root node has no successor */
-#if 0
- if (i < BTref->treeDepth-1)
- {
-#endif
- data_nodes[i+1].cur_rec++;
-#if 0
- }
- else
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- }
- i++;
- }
-
- if (is_extent && !extentEOL)
- {
- /* extract current leaf record and update maxExtentAB and
- maxExtentNode */
- hfs_extentKey *extentKey;
- hfs_extent *extentData;
-
- /* extract current leaf record */
- err = BT_node_get_keyed_record(BTref, data_nodes[0].buf, false, data_nodes[0].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- extentKey = (hfs_extentKey*)rec1;
- if ((extentKey->keyLength < 7) || (extentKey->forkType != 0) || (get_UINT32BE(extentKey->fileID) != 3)
- || (get_UINT16BE(extentKey->startBlock) != maxExtentAB))
- /* the key is corrupt or does not concern the extent
- B-tree: set the extentEOL flag so that we stop looking for
- further extent records for the extent B-tree */
- extentEOL = true;
- else
- { /* this key concerns the extent B-tree: update maxExtentAB
- and maxExtentNode */
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(hfs_extent)*3)
- /* the record is corrupt: set the extentEOL flag so
- that we stop looking for further extent records for the
- extent B-tree */
- extentEOL = true;
- else
- {
- extentData = (hfs_extent*)rec1_data;
-
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(extentData[j].numABlks);
- maxExtentNode = (uint64_t)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- }
- }
- if (extentEOL)
- {
- /* check that the extent B-Tree has been defined entirely */
- if (maxExtentNode < totalNodes)
- { /* no good */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- }
-
- if (i<BTref->treeDepth)
- {
- /* extract current record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract previous record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec-1, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* check that it is sorted correctly */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result <= 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- i--;
- }
- else
- {
- i--;
- if (i>0)
- { /* extract first record of root if it is an index node */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, true, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
- }
- i--;
- }
-
- while (i>=0)
- {
- /* extract first record of current level */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* compare key with key of current record of upper level */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result != 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
-
- /* compare node index with data of current record of upper
- level */
- if (cur_node != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- rec1 = rec2;
- rec1_len = rec2_len;
- i--;
- }
-
- /* next leaf record */
- data_nodes[0].cur_rec++;
- }
-
-end_of_list:
- /* check that we are at the end of list for each index level */
- for (i=1; i<BTref->treeDepth; i++)
- {
- if ((data_nodes[i].cur_rec != (data_nodes[i].num_recs-1))
- || get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* check that the last leaf node is what it is expected to be */
- if (data_nodes[0].node_num != lastLeafNode)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
-
- /* check map node chain */
- cur_node = 0; /* node 0 is the header node... */
- bitmap[0] |= 0x80;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- while (cur_node != 0)
- {
- /* save node address */
- prev_node = cur_node;
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks that
- forward and back linking match and that node height is correct are
- enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read map node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink) != prev_node)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- }
-
- /* re-read header node */
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- if (err)
- goto bail;
-
- /* get header bitmap record */
- err = BT_node_get_record(BTref, BTref->node_buf, 2, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* check bitmap, iterating map nodes */
- map_count = 0;
- actualFreeNodes = 0;
- while (map_count < map_len)
- {
- /* compute compare len */
- run_len = rec1_len;
- if (run_len > (map_len-map_count))
- run_len = map_len-map_count;
- /* check that all used nodes are marked as such in the B-tree bitmap */
- for (i=0; i<run_len; i++)
- if (bitmap[map_count+i] & ~((uint8_t *)rec1)[i])
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* count free nodes */
- run_bit_len = rec1_len*8;
- if (run_bit_len > (totalNodes-map_count*8))
- run_bit_len = totalNodes-map_count*8;
- for (i=0; i<run_bit_len; i++)
- if (! (((uint8_t *)rec1)[i>>3] & (0x80 >> (i & 7))))
- actualFreeNodes++;
- map_count += run_len;
- /* read next map node if required */
- if (map_count < map_len)
- {
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- if (cur_node == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* read map node */
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- if (err)
- goto bail;
- /* get map record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
- header_rec = (BTHeaderRecord *)rec1;
- }
- }
-
- /* check free node count */
- if (freeNodes != actualFreeNodes)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
-bail:
- /* free buffers */
- if (data_nodes)
- {
- for (i=0; i<BTref->treeDepth; i++)
- if (data_nodes[i].buf)
- free(data_nodes[i].buf);
- free(data_nodes);
- }
- if (bitmap)
- free(bitmap);
-
- return err;
-}
-
-/*
- BT_search_leaf_rec
-
- Search for a given key in a B-Tree. If exact match found, returns
- corresponding leaf record. Otherwise, may return the greatest record less
- than the requested key (of course, this will fail if the key is lower than
- all keys in the B-Tree).
-
- BTref (I/O): open B-tree file handle
- search_key (I): key to search the B-Tree for
- node_ID (O): set to the node ID of the node the record is located in (may
- be NULL)
- record_ID (O): set to the index of the record in the node (may be NULL)
- record_ptr (O): set to point to record in node buffer (may be NULL)
- record_len (O): set to total record len (may be NULL)
- search_exact_match (I): if true, the function will search for a record
- equal to search_key; if false, the function will search for the
- greatest record less than or equal to search_key
- match_found (O): set to true if an exact match for search_key has been
- found (only makes sense if search_exact_match is false) (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- uint32_t *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found)
-{
- imgtoolerr_t err;
- int i;
- uint32_t cur_node;
- void *cur_rec;
- int cur_rec_len;
- void *last_rec;
- int last_rec_len = 0;
- void *rec_data;
- int rec_data_len;
- int depth;
- uint16_t node_numRecords;
- int compare_result = 0;
-
- /* start with root node */
- if ((BTref->rootNode == 0) || (BTref->treeDepth == 0))
- /* tree is empty */
- return ((BTref->rootNode == 0) == (BTref->treeDepth == 0))
- ? IMGTOOLERR_FILENOTFOUND
- : IMGTOOLERR_CORRUPTIMAGE;
-
- cur_node = BTref->rootNode;
- depth = BTref->treeDepth;
-
- while (1)
- {
- /* read current node */
- err = BT_read_node(BTref, cur_node, (depth > 1) ? btnk_indexNode : btnk_leafNode, depth, BTref->node_buf);
- if (err)
- return err;
-
- /* search for key */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- last_rec = cur_rec = NULL;
- for (i=0; i<node_numRecords; i++)
- {
- err = BT_node_get_keyed_record(BTref, BTref->node_buf, depth > 1, i, &cur_rec, &cur_rec_len);
- if (err)
- return err;
-
- compare_result = (*BTref->key_compare_func)(cur_rec, search_key);
- if (compare_result > 0)
- break;
- last_rec = cur_rec;
- last_rec_len = cur_rec_len;
- if (compare_result == 0)
- break;
- }
-
- if (! last_rec)
- { /* all keys are greater than the search key: the search key is
- nowhere in the tree */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = false;
-
- if (node_ID)
- *node_ID = 0;
-
- if (record_ID)
- *record_ID = -1;
-
- if (record_ptr)
- *record_ptr = NULL;
-
- return IMGTOOLERR_SUCCESS;
- }
-
- if (((BTNodeHeader *) BTref->node_buf)->kind == btnk_leafNode)
- /* leaf node -> end of search */
- break;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, last_rec, last_rec_len, &rec_data, &rec_data_len);
- if (err)
- return err;
- if (rec_data_len < sizeof(UINT32BE))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec_data);
- depth--;
- }
-
- if (compare_result != 0)
- /* key not found */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = (compare_result == 0);
-
- if (node_ID)
- *node_ID = cur_node;
-
- if (record_ID)
- *record_ID = i;
-
- if (record_ptr)
- *record_ptr = last_rec;
-
- if (record_len)
- *record_len = last_rec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_open
-
- Open enumerator for leaf records of a B-Tree
-
- BTref (I/O): open B-tree file handle
- enumerator (O): B-Tree enumerator to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator)
-{
- enumerator->BTref = BTref;
- enumerator->cur_node = BTref->firstLeafNode;
- enumerator->cur_rec = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_read
-
- Read next leaf record of a B-Tree
-
- enumerator (I/O): open B-Tree enumerator
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len)
-{
- uint16_t node_numRecords;
- imgtoolerr_t err;
-
-
- *record_ptr = NULL;
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* read current node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
-
- /* skip nodes until we find a record */
- while ((enumerator->cur_rec >= node_numRecords) && (enumerator->cur_node != 0))
- {
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
-
- /* read node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
- }
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* get current record */
- err = BT_node_get_keyed_record(enumerator->BTref, enumerator->BTref->node_buf, false, enumerator->cur_rec, record_ptr, rec_len);
- if (err)
- return err;
-
- /* iterate to next record */
- enumerator->cur_rec++;
- if (enumerator->cur_rec >= node_numRecords)
- { /* iterate to next node if last record (not required, but will improve
- performance on next iteration) */
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- B-Tree extend EOF algorithm:
- * see if the bitmap will need to be extended
- * extend EOF by min 1 (if bitmap is large engough) or 2 (if bitmap needs
- to be extended) and max ClumpSiz (see extClpSiz and ctClpSiz in MDB)
- ***If we are extending the extent B-Tree, we need to defer the possible
- creation of an additional extent record, or we might enter an endless
- recursion loop***
-
- Empty node alloc algorithm:
-
- * see if there is any free node in B-tree bitmap
- * optionally, try to compact the B-tree if file is full
- * if file is still full, extend EOF and try again
- * mark new block as used and return its index
-
-
- Empty node delete algorithm:
-
- * remove node from link list
- * mark node as free in the B-tree bitmap
- * optionally, if more than N% of the B-tree is free, compact the B-tree and
- free some disk space
- * Count nodes on this level; if there is only one left, delete parent index
- node and mark the relaining node as root; if it was the last leaf node,
- update header node with an empty B-tree; in either case, decrement tree
- depth
-
-
- Record shifting algorithm:
-
- For a given node and its first non-empty successor node:
-
- * compute how much free room there is in the node
- * see if the first record of the first non-empty successor can fit
- * if so, move it (i.e. delete the first record of the later node, and add a
- copy of it to the end of the former)
-
-
- Node merging algorithm
-
- * Consider node and its predecessor. If there is room, shift all records
- from later to former, then delete empty later node, and delete later
- record from parent index node.
-
-
- Node splitting algorithm (non-first)
-
- * Consider node and its predecessor. Create new middle node and split
- records in 3 even sets. Update record for last node and insert record
- for middle node in parent index node.
-
-
- Node splitting algorithm (first node)
-
- * Create new successor node, and split records in 2 1/3 and 2/3 sets.
- Insert record for later node in parent index node.
-
-
- Record delete algorithm:
-
- * remove record from node
- * if record was first in node, test if node is now empty
- * if node is not empty, substitute key of deleted record with key of
- new head record in index tree
- * if node is empty, delete key of deleted record in index tree, then
- delete empty node
- * optionally, look the predecessor node. Merge the two nodes if possible.
-
-
- Record insert algorithm:
-
- * if there room, just insert new record in node; if new record is in first
- position, update record in parent index node
- * else consider predecessor: see if we can make enough room by shifting
- records. If so, do shift records, insert new record, update record in
- parent index node
- * else split the nodes and insert record
-*/
-/*
- Possible additions:
-
- Node compaction algorithm:
-
- This algorithm can be executed with a specific start point and max number
- of nodes, or with all nodes on a level.
-
- * see how many nodes we can save by shifting records left
- * if we will save at least one node, do shift as many records as possible
- (try to leave free space split homogeneously???)
-*/
-
-/*static void*/
-
-#if 0
-#pragma mark -
-#pragma mark RESOURCE IMPLEMENTATION
-#endif
-
-/*
- Resource manager
-
- The resource manager stores arbitrary chunks of data (resource) identified
- by a type/id pair. The resource type is a 4-char code, which generally
- implies the format of the data (e.g. 'PICT' is for a quickdraw picture,
- 'STR ' for a macintosh string, 'CODE' for 68k machine code, etc). The
- resource id is a signed 16-bit number that uniquely identifies each
- resource of a given type. Note that, with most resource types, resources
- with id < 128 are system resources that are available to all applications,
- whereas resources with id >= 128 are application resources visible only to
- the application that defines them.
-
- Each resource can optionally have a resource name, which is a macintosh
- string of 255 chars at most.
-
- Limits:
- 16MBytes of data
- 64kbytes of type+reference lists
- 64kbytes of resource names
-
- The Macintosh toolbox can open several resource files simulteanously to
- overcome these restrictions.
-
- Resources are used virtually everywhere in the Macintosh Toolbox, so it is
- no surprise that file comments and MFS folders are stored in resource files.
-*/
-
-/*
- Resource header
-*/
-struct rsrc_header
-{
- UINT32BE data_offs; /* Offset from beginning of resource fork to resource data */
- UINT32BE map_offs; /* Offset from beginning of resource fork to resource map */
- UINT32BE data_len; /* Length of resource data */
- UINT32BE map_len; /* Length of resource map */
-};
-
-/*
- Resource data: each data entry is preceded by its len (UINT32BE)
- Offset to specific data fields are gotten from the resource map
-*/
-
-/*
- Resource map:
-*/
-struct rsrc_map_header
-{
- rsrc_header reserved0; /* Reserved for copy of resource header */
- UINT32BE reserved1; /* Reserved for handle to next resource map */
- UINT16BE reserved2; /* Reserved for file reference number */
-
- UINT16BE attr; /* Resource fork attributes */
- UINT16BE typelist_offs; /* Offset from beginning of map to resource type list */
- UINT16BE namelist_offs; /* Offset from beginning of map to resource name list */
- UINT16BE type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-/*
- Resource type list entry
-*/
-struct rsrc_type_entry
-{
- UINT32BE type; /* Resource type */
- UINT16BE ref_count; /* Number of resources of this type in map minus 1 */
- UINT16BE ref_offs; /* Offset from beginning of resource type list to reference list for this type */
-};
-
-/*
- Resource reference list entry
-*/
-struct rsrc_ref_entry
-{
- UINT16BE id; /* Resource ID */
- UINT16BE name_offs; /* Offset from beginning of resource name list to resource name */
- /* (-1 if none) */
- uint8_t attr; /* Resource attributes */
- UINT24BE data_offs; /* Offset from beginning of resource data to data for this resource */
- UINT32BE reserved; /* Reserved for handle to resource */
-};
-
-/*
- Resource name list entry: this is just a standard macintosh string
-*/
-
-struct mac_resfileref
-{
- mac_fileref fileref; /* open resource fork ref (you may open resources
- files in data fork, too, if you ever need to,
- but Classic MacOS never does such a thing
- (MacOS X often does so, though)) */
- uint32_t data_offs; /* Offset from beginning of resource file to resource data */
- uint32_t map_offs; /* Offset from beginning of resource file to resource data */
-
- uint16_t typelist_offs; /* Offset from beginning of map to resource type list */
- uint16_t namelist_offs; /* Offset from beginning of map to resource name list */
- uint16_t type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-#ifdef UNUSED_FUNCTION
-/*
- resfile_open
-
- Open a file as a resource file. The file must be already open as a
- macintosh file.
-
- resfileref (I/O): resource file handle to open (resfileref->fileref must
- have been opened previously)
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_open(mac_resfileref *resfileref)
-{
- imgtoolerr_t err;
- rsrc_header header;
- rsrc_map_header map_header;
-
- /* seek to resource header */
- err = mac_file_seek(&resfileref->fileref, 0);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(header), &header);
- if (err)
- return err;
-
- resfileref->data_offs = get_UINT32BE(header.data_offs);
- resfileref->map_offs = get_UINT32BE(header.map_offs);
-
- /* seek to resource map header */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(map_header), &map_header);
- if (err)
- return err;
-
- resfileref->typelist_offs = get_UINT16BE(map_header.typelist_offs);
- resfileref->namelist_offs = get_UINT16BE(map_header.namelist_offs);
- resfileref->type_count = get_UINT16BE(map_header.type_count);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_entry
-
- Get the resource entry in the resource map associated with a given type/id
- pair.
-
- resfileref (I/O): open resource file handle
- type (I): type of the resource
- id (I): id of the resource
- entry (O): resource entry that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_entry(mac_resfileref *resfileref, uint32_t type, uint16_t id, rsrc_ref_entry *entry)
-{
- imgtoolerr_t err;
- rsrc_type_entry type_entry;
- uint16_t ref_count;
- int i;
-
- /* seek to resource type list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+2);
- if (err)
- return err;
-
- if (resfileref->type_count == 0xffff)
- /* type list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=resfileref->type_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(type_entry), &type_entry);
- if (err)
- return err;
- if (type == get_UINT32BE(type_entry.type))
- break;
- }
- if (i > resfileref->type_count)
- /* type not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- ref_count = get_UINT16BE(type_entry.ref_count);
-
- /* seek to resource ref list for this type in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+get_UINT16BE(type_entry.ref_offs));
- if (err)
- return err;
-
- if (ref_count == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=ref_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(*entry), entry);
- if (err)
- return err;
- if (id == get_UINT16BE(entry->id))
- break;
- }
- if (i > ref_count)
- /* id not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- /* type+id have been found... */
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resname
-
- Get the name of a resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- string (O): resource name
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resname(mac_resfileref *resfileref, const rsrc_ref_entry *entry, mac_str255 string)
-{
- imgtoolerr_t err;
- uint16_t name_offs;
- uint8_t len;
-
- name_offs = get_UINT16BE(entry->name_offs);
-
- if (name_offs == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_UNEXPECTED;
-
- /* seek to resource name in name list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+name_offs);
- if (err)
- return err;
-
- /* get string length */
- err = mac_file_read(&resfileref->fileref, 1, &len);
- if (err)
- return err;
-
- string[0] = len;
-
- /* get string data */
- err = mac_file_read(&resfileref->fileref, len, string+1);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_reslen
-
- Get the data length for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- len (O): resource length
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_reslen(mac_resfileref *resfileref, const rsrc_ref_entry *entry, uint32_t *len)
-{
- imgtoolerr_t err;
- uint32_t data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- *len = get_UINT32BE(llen);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resdata
-
- Get the data for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- offset (I): offset the data should be read from, usually 0
- len (I): length of the data to read, usually the value returned by
- resfile_get_reslen
- dest (O): resource data
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resdata(mac_resfileref *resfileref, const rsrc_ref_entry *entry, uint32_t offset, uint32_t len, void *dest)
-{
- imgtoolerr_t err;
- uint32_t data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- /* check that we do not ask to read more data than avalaible */
- if ((offset + len) > get_UINT32BE(llen))
- return IMGTOOLERR_UNEXPECTED;
-
- if (offset)
- { /* seek to resource data offset in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs+4+offset);
- if (err)
- return err;
- }
-
- /* get data */
- err = mac_file_read(&resfileref->fileref, len, dest);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark DESKTOP FILE IMPLEMENTATION
-#endif
-/*
- All macintosh volumes have information stored in the desktop file or the
- desktop database.
-
- Such information include file comments, copy of BNDL and FREF resources
- that describes supported file types for each application on the volume,
- copy of icons for each file type registered by each application on the
- volume, etc. On MFS volumes, the list of folders is stored in the desktop
- file as well.
-
-
- There have been two implementations of the desktop metadata:
-
- * The original desktop file. The database is stored in the resource fork
- of a (usually invisible) file called "Desktop" (case may change
- according to system versions), located at the root of the volume. The
- desktop file is used by System 6 and earlier for all volumes (unless
- Appleshare 2 is installed and the volume is shared IIRC), and by System
- 7 and later for volumes smaller than 2MBytes (so that floppy disks
- remain fully compatible with earlier versions of system). The desktop
- file is incompletely documented by Apple technote TB06.
-
- * The desktop database. The database is stored in the resource fork is
- stored in the data fork of two (usually invisible) files called
- "Desktop DF" and "Desktop DF". The desktop database is used for
- volumes shared by Appleshare 2, and for most volumes under System 7 and
- later. The format of these file is not documented AFAIK.
-
-
- The reasons for the introduction of the desktop database were:
- * the macintosh resource manager cannot share resource files, which was
- a problem for Appleshare
- * the macintosh resource manager is pretty limited (+/-16MByte of data and
- 2727 resources at most), which was a problem for large hard disks with
- many programs/comments
-*/
-
-#ifdef UNUSED_FUNCTION
-/*
- get_comment
-
- Get a comment from the Desktop file
-
- l2_img (I): macintosh image the data should be read from
- id (I): comment id (from mfs_hashString(), or HFS FXInfo/DXInfo records)
- comment (O): comment that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t get_comment(struct mac_l2_imgref *l2_img, uint16_t id, mac_str255 comment)
-{
- static const uint8_t desktop_fname[] = {'\7','D','e','s','k','t','o','p'};
- #define restype_FCMT (('F' << 24) | ('C' << 16) | ('M' << 8) | 'T')
- mac_resfileref resfileref;
- rsrc_ref_entry resentry;
- uint32_t reslen;
- imgtoolerr_t err;
-
- /* open rsrc fork of file Desktop in root directory */
- err = mac_file_open(l2_img, 2, desktop_fname, rsrc_fork, &resfileref.fileref);
- if (err)
- return err;
-
- /* open resource structures */
- err = resfile_open(&resfileref);
- if (err)
- return err;
-
- /* look for resource FCMT #id */
- err = resfile_get_entry(&resfileref, restype_FCMT, id, &resentry);
- if (err)
- return err;
-
- /* extract comment len */
- err = resfile_get_reslen(&resfileref, &resentry, &reslen);
- if (err)
- return err;
-
- /* check comment len */
- if (reslen > 256)
- /* hurk */
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- /* people willing to extend the MFM comment field (you know, the kind
- of masochists that try to support 20-year-old OSes) might append extra
- fields, so we just truncate the resource */
- reslen = 256;
-
- /* extract comment data */
- err = resfile_get_resdata(&resfileref, &resentry, 0, reslen, comment);
- if (err)
- return err;
-
- /* phew, we are done! */
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark IMGTOOL MODULE IMPLEMENTATION
-#endif
-
-#ifdef UNUSED_FUNCTION
-static void mac_image_exit(imgtool::image *img);
-#endif
-static void mac_image_info(imgtool::image &img, std::ostream &stream);
-static imgtoolerr_t mac_image_beginenum(imgtool::directory &enumeration, const char *path);
-static imgtoolerr_t mac_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent);
-static imgtoolerr_t mac_image_freespace(imgtool::partition &partition, uint64_t *size);
-static imgtoolerr_t mac_image_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf);
-static imgtoolerr_t mac_image_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions);
-
-#ifdef UNUSED_FUNCTION
-/*
- close a mfs/hfs image
-*/
-static void mac_image_exit(imgtool::image *img)
-{
- struct mac_l2_imgref *image = get_imgref(img);
-
- mac_image_close(image);
-}
-#endif
-
-/*
- get basic information on a mfs/hfs image
-
- Currently returns the volume name
-*/
-static void mac_image_info(imgtool::image &img, std::ostream &stream)
-{
- char buffer[256] = { 0, };
- struct mac_l2_imgref *image = get_imgref(img);
-
- switch (image->format)
- {
- case L2I_MFS:
- mac_to_c_strncpy(buffer, ARRAY_LENGTH(buffer), image->u.mfs.volname);
- break;
-
- case L2I_HFS:
- mac_to_c_strncpy(buffer, ARRAY_LENGTH(buffer), image->u.hfs.volname);
- break;
- }
-
- stream << buffer;
-}
-
-/*
- MFS/HFS catalog iterator, used when imgtool reads the catalog
-*/
-struct mac_iterator
-{
- mac_format format;
- struct mac_l2_imgref *l2_img;
- union
- {
- struct
- {
- mfs_dirref dirref; /* open directory reference */
- } mfs;
- struct
- {
- hfs_cat_enumerator catref; /* catalog file enumerator */
- } hfs;
- } u;
-};
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t mac_image_beginenum(imgtool::directory &enumeration, const char *path)
-{
- struct mac_l2_imgref *image = get_imgref(enumeration.image());
- mac_iterator *iter = (mac_iterator *) enumeration.extra_bytes();
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- iter->format = image->format;
- iter->l2_img = image;
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_dir_open(image, path, &iter->u.mfs.dirref);
- break;
-
- case L2I_HFS:
- err = hfs_cat_open(image, path, &iter->u.hfs.catref);
- break;
- }
-
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry (MFS)
-*/
-static imgtoolerr_t mfs_image_nextenum(mac_iterator *iter, imgtool_dirent &ent)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
-
- assert(iter->format == L2I_MFS);
-
- ent.corrupt = 0;
- ent.eof = 0;
-
- err = mfs_dir_read(&iter->u.mfs.dirref, &cur_dir_entry);
- if (err)
- {
- /* error */
- ent.corrupt = 1;
- return err;
- }
- else if (!cur_dir_entry)
- {
- /* EOF */
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* copy info */
- mac_to_c_strncpy(ent.filename, ARRAY_LENGTH(ent.filename), cur_dir_entry->name);
- ent.filesize = get_UINT32BE(cur_dir_entry->dataPhysicalSize)
- + get_UINT32BE(cur_dir_entry->rsrcPhysicalSize);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-/*
- Concatenate path elements in the reverse order
-
- dest (O): destination buffer
- dest_cur_pos (I/O): current position in destination buffer (buffer is
- filled from end to start)
- dest_max_len (I): length of destination buffer (use length minus one if you
- want to preserve a trailing NUL character)
- src (I): source C string
-*/
-static void concat_fname(char *dest, int *dest_cur_pos, int dest_max_len, const char *src)
-{
- static const char ellipsis[] = { '.', '.', '.' };
- int src_len = strlen(src); /* number of chars from src to insert */
-
- if (src_len <= *dest_cur_pos)
- {
- *dest_cur_pos -= src_len;
- memcpy(dest + *dest_cur_pos, src, src_len);
- }
- else
- {
- memcpy(dest, src + src_len - *dest_cur_pos, *dest_cur_pos);
- *dest_cur_pos = 0;
- memcpy(dest, ellipsis, (sizeof(ellipsis) <= dest_max_len)
- ? sizeof(ellipsis)
- : dest_max_len);
- }
-}
-#endif
-
-/*
- Enumerate disk catalog next entry (HFS)
-*/
-static imgtoolerr_t hfs_image_nextenum(mac_iterator *iter, imgtool_dirent &ent)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- uint16_t dataRecType;
- imgtoolerr_t err;
- /* currently, the mac->C conversion transcodes one mac char with at most 3
- C chars */
- int cur_name_head;
-
- assert(iter->format == L2I_HFS);
-
- ent.corrupt = 0;
- ent.eof = 0;
-
- do
- {
- err = hfs_cat_read(&iter->u.hfs.catref, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- ent.corrupt = 1;
- return err;
- }
- else if (!catrec_key)
- {
- /* EOF */
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
- dataRecType = get_UINT16BE(catrec_data->dataType);
- } while (((dataRecType != hcrt_Folder) && (dataRecType != hcrt_File))
- || (get_UINT32BE(catrec_key->parID) != iter->u.hfs.catref.parID));
-
- /* copy info */
- switch (get_UINT16BE(catrec_data->dataType))
- {
- case hcrt_Folder:
- ent.directory = 1;
- ent.filesize = 0;
- break;
-
- case hcrt_File:
- ent.directory = 0;
- ent.filesize = get_UINT32BE(catrec_data->file.dataPhysicalSize)
- + get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- break;
- }
-
- /* initialize file path buffer */
- cur_name_head = ARRAY_LENGTH(ent.filename);
- if (cur_name_head > 0)
- {
- cur_name_head--;
- ent.filename[cur_name_head] = '\0';
- }
-
- /* insert folder/file name in buffer */
- mac_to_c_strncpy(ent.filename, ARRAY_LENGTH(ent.filename), catrec_key->cName);
-// concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, buf);
-
-#if 0
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_key->parID);
-
- /* looping while (parID != 1) will display the volume name; looping while
- (parID != 2) won't */
- while (parID != /*1*/2)
- {
- /* search catalog for folder thread */
- err = hfs_cat_search(iter->l2_img, parID, mac_empty_str, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, "???");
-
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename) - cur_name_head);
- ent.corrupt = 1;
- return err;
- }
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- if (dataRecType != hcrt_FolderThread)
- {
- /* error */
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename)-1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename)-1, "???");
-
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename)-cur_name_head);
- ent.corrupt = 1;
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* got folder thread record: insert the folder name at the start of
- file path, then iterate */
- mac_to_c_strncpy(buf, sizeof(buf), catrec_data->thread.nodeName);
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, buf);
-
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_data->thread.parID);
- }
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename) -cur_name_head);
-#endif
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t mac_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
-{
- imgtoolerr_t err;
- mac_iterator *iter = (mac_iterator *) enumeration.extra_bytes();
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_image_nextenum(iter, ent);
- break;
-
- case L2I_HFS:
- err = hfs_image_nextenum(iter, ent);
- break;
-
- default:
- assert(1);
- err = IMGTOOLERR_UNEXPECTED;
- break;
- }
- return err;
-}
-
-/*
- Compute free space on disk image in bytes
-*/
-static imgtoolerr_t mac_image_freespace(imgtool::partition &partition, uint64_t *size)
-{
- imgtool::image &image(partition.image());
- *size = ((uint64_t) get_imgref(image)->freeABs) * 512;
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t mac_get_comment(struct mac_l2_imgref *image, mac_str255 filename, const mac_dirent *cat_info, mac_str255 comment)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- uint16_t commentID;
-
- comment[0] = '\0';
-
- /* get comment from Desktop file */
- switch (image->format)
- {
- case L2I_MFS:
- commentID = mfs_hashString(filename);
- err = get_comment(image, commentID, comment);
- break;
-
- case L2I_HFS:
- /* This is the way to get Finder comments in system <= 7. Attached
- comments use another method, and Finder 8 uses yet another one. */
- commentID = get_UINT16BE(cat_info->flXFinderInfo.comment);
- if (commentID)
- err = get_comment(image, commentID, comment);
- break;
- }
- return err;
-}
-#endif
-
-
-/*
- Extract a file from a disk image.
-*/
-static imgtoolerr_t mac_image_readfile(imgtool::partition &partition, const char *fpath, const char *fork, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- uint8_t buf[512];
- uint32_t i, run_len, data_len;
- mac_fork_t fork_num;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* open file */
- err = mac_file_open(image, parID, filename, fork_num ? rsrc_fork : data_fork, &fileref);
- if (err)
- return err;
-
- data_len = fork_num ? cat_info.rsrcLogicalSize : cat_info.dataLogicalSize;
-
- /* extract DF */
- i = 0;
- while(i < data_len)
- {
- run_len = std::min(size_t(data_len - i), sizeof(buf));
-
- err = mac_file_read(&fileref, run_len, buf);
- if (err)
- return err;
- if (destf.write(buf, run_len) != run_len)
- return IMGTOOLERR_WRITEERROR;
- i += run_len;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Add a file to a disk image.
-*/
-static imgtoolerr_t mac_image_writefile(imgtool::partition &partition, const char *fpath, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions)
-{
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- uint32_t fork_len;
- /*uint16_t commentID;*/
- /*mac_str255 comment;*/
- uint8_t buf[512];
- uint32_t i, run_len;
- imgtoolerr_t err;
- mac_fork_t fork_num;
-
- (void) writeoptions;
-
- if (image->format == L2I_HFS)
- return IMGTOOLERR_UNIMPLEMENTED;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
-#if 0
- if (header.version_old != 0)
- return IMGTOOLERR_UNIMPLEMENTED;
-#endif
- /*mac_strcpy(filename, header.filename);*/
- memset(&cat_info, 0, sizeof(cat_info));
- set_UINT32BE(&cat_info.flFinderInfo.type, 0x3F3F3F3F);
- set_UINT32BE(&cat_info.flFinderInfo.creator, 0x3F3F3F3F);
- fork_len = sourcef.size();
- /*comment[0] = get_UINT16BE(header.comment_len);*/ /* comment length */
- /* Next two fields are set to 0 with MFS volumes. IIRC, 0 normally
- means system script: I don't think MFS stores the file name script code
- anywhere on disk, so it should be a reasonable approximation. */
-
- /* create file */
- /* clear inited flag and file location in window */
- set_UINT16BE(&cat_info.flFinderInfo.flags, get_UINT16BE(cat_info.flFinderInfo.flags) & ~fif_hasBeenInited);
- set_UINT16BE(&cat_info.flFinderInfo.location.v, 0);
- set_UINT16BE(&cat_info.flFinderInfo.location.h, 0);
-
- /* resolve path and create file */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, true);
- if (err)
- return err;
-
- /* open file fork */
- err = mac_file_open(image, parID, filename, (fork_num ? rsrc_fork : data_fork), &fileref);
- if (err)
- return err;
-
- err = mac_file_seteof(&fileref, fork_len);
- if (err)
- return err;
-
- /* extract fork */
- for (i=0; i<fork_len;)
- {
- run_len = fork_len - i;
- if (run_len > 512)
- run_len = 512;
- if (sourcef.read(buf, run_len) != run_len)
- return IMGTOOLERR_READERROR;
- err = mac_file_write(&fileref, run_len, buf);
- if (err)
- return err;
- i += run_len;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_listforks(imgtool::partition &partition, const char *path, std::vector<imgtool::fork_entry> &forks)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- // specify data fork
- forks.emplace_back(cat_info.dataLogicalSize, imgtool::fork_entry::type_t::DATA);
-
- if (cat_info.rsrcLogicalSize > 0)
- {
- // specify the resource fork
- forks.emplace_back(cat_info.rsrcLogicalSize, imgtool::fork_entry::type_t::RESOURCE);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_getattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &img(partition.image());
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.type);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.creator);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.flags);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.h);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.v);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.fldr);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.iconID);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = cat_info.flXFinderInfo.script;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = cat_info.flXFinderInfo.XFlags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.comment);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = get_UINT32BE(cat_info.flXFinderInfo.putAway);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = mac_crack_time(cat_info.createDate).to_time_t();
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = mac_crack_time(cat_info.modifyDate).to_time_t();
- break;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_setattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- set_UINT32BE(&cat_info.flFinderInfo.type, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- set_UINT32BE(&cat_info.flFinderInfo.creator, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- set_UINT16BE(&cat_info.flFinderInfo.flags, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- set_UINT16BE(&cat_info.flFinderInfo.location.h, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- set_UINT16BE(&cat_info.flFinderInfo.location.v, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- set_UINT16BE(&cat_info.flFinderInfo.fldr, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- set_UINT16BE(&cat_info.flXFinderInfo.iconID, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- cat_info.flXFinderInfo.script = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- cat_info.flXFinderInfo.XFlags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- set_UINT16BE(&cat_info.flXFinderInfo.comment, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- set_UINT32BE(&cat_info.flXFinderInfo.putAway, values[i].i);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- cat_info.createDate = mac_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- cat_info.modifyDate = mac_setup_time(values[i].t);
- break;
- }
- }
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, true);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
- *
- * Our very own resource manager
- *
- *************************************/
-
-static const void *mac_walk_resources(const void *resource_fork, size_t resource_fork_length,
- uint32_t resource_type,
- int (*discriminator)(const void *resource, uint16_t id, uint32_t length, void *param_),
- void *param, uint16_t *resource_id, uint32_t *resource_length)
-{
- uint32_t resource_data_offset, resource_data_length;
- uint32_t resource_map_offset, resource_map_length;
- uint32_t resource_typelist_count, resource_typelist_offset;
- uint32_t resource_entry_offset, resource_entry_count;
- uint32_t i, this_resource_type;
- uint32_t this_resource_data, this_resource_length;
- uint16_t this_resource_id;
- const void *this_resource_ptr;
-
- if (resource_fork_length < 16)
- return NULL;
-
- /* read resource header; its ok if anything past this point fails */
- resource_data_offset = pick_integer_be(resource_fork, 0, 4);
- resource_map_offset = pick_integer_be(resource_fork, 4, 4);
- resource_data_length = pick_integer_be(resource_fork, 8, 4);
- resource_map_length = pick_integer_be(resource_fork, 12, 4);
- if ((resource_data_offset + resource_data_length) > resource_fork_length)
- return NULL;
- if ((resource_map_offset + resource_map_length) > resource_fork_length)
- return NULL;
- if (resource_map_length < 30)
- return NULL;
-
- /* read resource map and locate the resource type list */
- resource_typelist_offset = pick_integer_be(resource_fork,
- resource_map_offset + 24, 2) + resource_map_offset;
- if ((resource_typelist_offset + 2) > resource_fork_length)
- return NULL;
- resource_typelist_count = pick_integer_be(resource_fork,
- resource_typelist_offset, 2) + 1;
- if ((resource_typelist_offset + resource_typelist_count * 16 + 2) > resource_fork_length)
- return NULL;
-
- /* scan the resource type list and locate the entries for this type */
- resource_entry_count = 0;
- resource_entry_offset = 0;
- for (i = 0; i < resource_typelist_count; i++)
- {
- this_resource_type = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 0, 4);
- if (this_resource_type == resource_type)
- {
- resource_entry_count = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 4, 2) + 1;
- resource_entry_offset = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 6, 2) + resource_typelist_offset;
- break;
- }
- }
-
- /* scan the resource entries, and find the correct resource */
- for (i = 0; i < resource_entry_count; i++)
- {
- this_resource_id = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 0, 2);
- this_resource_data = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 5, 3) + resource_data_offset;
- if ((this_resource_data + 4) > resource_fork_length)
- return NULL;
-
- /* gauge the length */
- this_resource_length = pick_integer_be(resource_fork, this_resource_data, 4);
- this_resource_data += 4;
- if ((this_resource_data + this_resource_length) > resource_fork_length)
- return NULL;
-
- this_resource_ptr = ((const uint8_t *) resource_fork) + this_resource_data;
- if (discriminator(this_resource_ptr, this_resource_id,
- this_resource_length, param))
- {
- if (resource_length)
- *resource_length = this_resource_length;
- if (resource_id)
- *resource_id = this_resource_id;
- return this_resource_ptr;
- }
- }
-
- return NULL;
-}
-
-
-
-static int get_resource_discriminator(const void *resource, uint16_t id, uint32_t length, void *param)
-{
- const uint16_t *id_ptr = (const uint16_t *) param;
- return id == *id_ptr;
-}
-
-
-
-static const void *mac_get_resource(const void *resource_fork, size_t resource_fork_length,
- uint32_t resource_type, uint16_t resource_id, uint32_t *resource_length)
-{
- return mac_walk_resources(resource_fork, resource_fork_length,
- resource_type, get_resource_discriminator, &resource_id, NULL, resource_length);
-}
-
-
-
-/*************************************
- *
- * Custom icons
- *
- *************************************/
-
-static int bundle_discriminator(const void *resource, uint16_t id, uint32_t length, void *param)
-{
- uint32_t this_creator_code = pick_integer_be(resource, 0, 4);
- uint32_t desired_creator_code = *((uint32_t *) param);
- return this_creator_code == desired_creator_code;
-}
-
-
-
-static uint8_t get_pixel(const uint8_t *src, int width, int height, int bpp,
- int x, int y)
-{
- uint8_t byte, mask;
- int bit_position;
-
- byte = src[(y * width + x) * bpp / 8];
- bit_position = 8 - ((x % (8 / bpp)) + 1) * bpp;
- mask = (1 << bpp) - 1;
- return (byte >> bit_position) & mask;
-}
-
-
-
-static bool load_icon(uint32_t *dest, const void *resource_fork, uint64_t resource_fork_length,
- uint32_t resource_type, uint16_t resource_id, int width, int height, int bpp,
- const uint32_t *palette, bool has_mask)
-{
- bool success = false;
- uint32_t frame_length = width * height * bpp / 8;
- uint32_t total_length = frame_length * (has_mask ? 2 : 1);
- uint32_t resource_length;
-
- // attempt to fetch resource
- const uint8_t *src = (const uint8_t*)mac_get_resource(resource_fork, resource_fork_length, resource_type,
- resource_id, &resource_length);
- if (src && (resource_length == total_length))
- {
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x ++)
- {
- // check the color
- uint8_t color = get_pixel(src, width, height, bpp, x, y);
-
- // then check the mask
- bool is_masked = has_mask
- ? get_pixel(src + frame_length, width, height, bpp, x, y) != 0
- : dest[y * width + x] >= 0x80000000;
-
- // is this actually masked? (note there is a special case when bpp == 1; Mac B&W icons
- // had a XOR effect, and this cannot be blocked by the mask)
- uint32_t pixel;
- if (is_masked || (color && bpp == 1))
- {
- // mask is ok; check the actual icon
- pixel = palette[color] | 0xFF000000;
- }
- else
- {
- // masked out; nothing
- pixel = 0x00000000;
- }
-
- dest[y * width + x] = pixel;
- }
- }
- success = true;
- }
- return success;
-}
-
-
-
-static imgtoolerr_t mac_image_geticoninfo(imgtool::partition &partition, const char *path, imgtool_iconinfo *iconinfo)
-{
- static const uint32_t mac_palette_1bpp[2] = { 0xFFFFFF, 0x000000 };
-
- static const uint32_t mac_palette_4bpp[16] =
- {
- 0xFFFFFF, 0xFCF305, 0xFF6402, 0xDD0806, 0xF20884, 0x4600A5,
- 0x0000D4, 0x02ABEA, 0x1FB714, 0x006411, 0x562C05, 0x90713A,
- 0xC0C0C0, 0x808080, 0x404040, 0x000000
- };
-
- static const uint32_t mac_palette_8bpp[256] =
- {
- 0xFFFFFF, 0xFFFFCC, 0xFFFF99, 0xFFFF66, 0xFFFF33, 0xFFFF00,
- 0xFFCCFF, 0xFFCCCC, 0xFFCC99, 0xFFCC66, 0xFFCC33, 0xFFCC00,
- 0xFF99FF, 0xFF99CC, 0xFF9999, 0xFF9966, 0xFF9933, 0xFF9900,
- 0xFF66FF, 0xFF66CC, 0xFF6699, 0xFF6666, 0xFF6633, 0xFF6600,
- 0xFF33FF, 0xFF33CC, 0xFF3399, 0xFF3366, 0xFF3333, 0xFF3300,
- 0xFF00FF, 0xFF00CC, 0xFF0099, 0xFF0066, 0xFF0033, 0xFF0000,
- 0xCCFFFF, 0xCCFFCC, 0xCCFF99, 0xCCFF66, 0xCCFF33, 0xCCFF00,
- 0xCCCCFF, 0xCCCCCC, 0xCCCC99, 0xCCCC66, 0xCCCC33, 0xCCCC00,
- 0xCC99FF, 0xCC99CC, 0xCC9999, 0xCC9966, 0xCC9933, 0xCC9900,
- 0xCC66FF, 0xCC66CC, 0xCC6699, 0xCC6666, 0xCC6633, 0xCC6600,
- 0xCC33FF, 0xCC33CC, 0xCC3399, 0xCC3366, 0xCC3333, 0xCC3300,
- 0xCC00FF, 0xCC00CC, 0xCC0099, 0xCC0066, 0xCC0033, 0xCC0000,
- 0x99FFFF, 0x99FFCC, 0x99FF99, 0x99FF66, 0x99FF33, 0x99FF00,
- 0x99CCFF, 0x99CCCC, 0x99CC99, 0x99CC66, 0x99CC33, 0x99CC00,
- 0x9999FF, 0x9999CC, 0x999999, 0x999966, 0x999933, 0x999900,
- 0x9966FF, 0x9966CC, 0x996699, 0x996666, 0x996633, 0x996600,
- 0x9933FF, 0x9933CC, 0x993399, 0x993366, 0x993333, 0x993300,
- 0x9900FF, 0x9900CC, 0x990099, 0x990066, 0x990033, 0x990000,
- 0x66FFFF, 0x66FFCC, 0x66FF99, 0x66FF66, 0x66FF33, 0x66FF00,
- 0x66CCFF, 0x66CCCC, 0x66CC99, 0x66CC66, 0x66CC33, 0x66CC00,
- 0x6699FF, 0x6699CC, 0x669999, 0x669966, 0x669933, 0x669900,
- 0x6666FF, 0x6666CC, 0x666699, 0x666666, 0x666633, 0x666600,
- 0x6633FF, 0x6633CC, 0x663399, 0x663366, 0x663333, 0x663300,
- 0x6600FF, 0x6600CC, 0x660099, 0x660066, 0x660033, 0x660000,
- 0x33FFFF, 0x33FFCC, 0x33FF99, 0x33FF66, 0x33FF33, 0x33FF00,
- 0x33CCFF, 0x33CCCC, 0x33CC99, 0x33CC66, 0x33CC33, 0x33CC00,
- 0x3399FF, 0x3399CC, 0x339999, 0x339966, 0x339933, 0x339900,
- 0x3366FF, 0x3366CC, 0x336699, 0x336666, 0x336633, 0x336600,
- 0x3333FF, 0x3333CC, 0x333399, 0x333366, 0x333333, 0x333300,
- 0x3300FF, 0x3300CC, 0x330099, 0x330066, 0x330033, 0x330000,
- 0x00FFFF, 0x00FFCC, 0x00FF99, 0x00FF66, 0x00FF33, 0x00FF00,
- 0x00CCFF, 0x00CCCC, 0x00CC99, 0x00CC66, 0x00CC33, 0x00CC00,
- 0x0099FF, 0x0099CC, 0x009999, 0x009966, 0x009933, 0x009900,
- 0x0066FF, 0x0066CC, 0x006699, 0x006666, 0x006633, 0x006600,
- 0x0033FF, 0x0033CC, 0x003399, 0x003366, 0x003333, 0x003300,
- 0x0000FF, 0x0000CC, 0x000099, 0x000066, 0x000033, 0xEE0000,
- 0xDD0000, 0xBB0000, 0xAA0000, 0x880000, 0x770000, 0x550000,
- 0x440000, 0x220000, 0x110000, 0x00EE00, 0x00DD00, 0x00BB00,
- 0x00AA00, 0x008800, 0x007700, 0x005500, 0x004400, 0x002200,
- 0x001100, 0x0000EE, 0x0000DD, 0x0000BB, 0x0000AA, 0x000088,
- 0x000077, 0x000055, 0x000044, 0x000022, 0x000011, 0xEEEEEE,
- 0xDDDDDD, 0xBBBBBB, 0xAAAAAA, 0x888888, 0x777777, 0x555555,
- 0x444444, 0x222222, 0x111111, 0x000000
- };
-
- static const uint32_t attrs[4] =
- {
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS
- };
-
- imgtoolerr_t err;
- imgtool_attribute attr_values[3];
- uint32_t type_code, creator_code, finder_flags;
- imgtool::stream::ptr stream;
- const void *resource_fork;
- uint64_t resource_fork_length;
- const void *bundle;
- uint32_t bundle_length, pos, fref_pos, icn_pos, i;
- uint16_t local_id = 0, resource_id;
- uint32_t fref_bundleentry_length, icn_bundleentry_length;
- const void *fref;
- uint32_t resource_length;
-
- assert((ARRAY_LENGTH(attrs) - 1)
- == ARRAY_LENGTH(attr_values));
-
- /* first retrieve type and creator code */
- err = mac_image_getattrs(partition, path, attrs, attr_values);
- if (err)
- return err;
- type_code = (uint32_t) attr_values[0].i;
- creator_code = (uint32_t) attr_values[1].i;
- finder_flags = (uint32_t) attr_values[2].i;
-
- /* check the bundle bit; if clear (and the type is not 'APPL'), use the
- * desktop file */
- if (!(finder_flags & 0x2000) && (type_code != /* APPL */ 0x4150504C))
- path = "Desktop\0";
-
- stream = imgtool::stream::open_mem(NULL, 0);
- if (!stream)
- return IMGTOOLERR_SUCCESS;
-
- /* read in the resource fork */
- err = mac_image_readfile(partition, path, "RESOURCE_FORK", *stream);
- if (err)
- return err;
- resource_fork = stream->getptr();
- resource_fork_length = stream->size();
-
- /* attempt to look up the bundle */
- bundle = mac_walk_resources(resource_fork, resource_fork_length, /* BNDL */ 0x424E444C,
- bundle_discriminator, &creator_code, NULL, &bundle_length);
- if (!bundle)
- return err;
-
- /* find the FREF and the icon family */
- pos = 8;
- fref_pos = icn_pos = 0;
- fref_bundleentry_length = icn_bundleentry_length = 0;
- while((pos + 10) <= bundle_length)
- {
- uint32_t this_bundleentry_type = pick_integer_be(bundle, pos + 0, 4);
- uint32_t this_bundleentry_length = pick_integer_be(bundle, pos + 4, 2) + 1;
-
- if (this_bundleentry_type == /* FREF */ 0x46524546)
- {
- fref_pos = pos;
- fref_bundleentry_length = this_bundleentry_length;
- }
- if (this_bundleentry_type == /* ICN# */ 0x49434E23)
- {
- icn_pos = pos;
- icn_bundleentry_length = this_bundleentry_length;
- }
- pos += 6 + this_bundleentry_length * 4;
- }
- if (!fref_pos || !icn_pos)
- return err;
-
- /* look up the FREF */
- for (i = 0; i < fref_bundleentry_length; i++)
- {
- local_id = pick_integer_be(bundle, fref_pos + (i * 4) + 6, 2);
- resource_id = pick_integer_be(bundle, fref_pos + (i * 4) + 8, 2);
-
- fref = mac_get_resource(resource_fork, resource_fork_length,
- /* FREF */ 0x46524546, resource_id, &resource_length);
- if (fref && (resource_length >= 7))
- {
- if (pick_integer_be(fref, 0, 4) == type_code)
- break;
- }
- }
- if (i >= fref_bundleentry_length)
- return err;
-
- /* now look up the icon family */
- resource_id = 0;
- for (i = 0; i < icn_bundleentry_length; i++)
- {
- if (pick_integer_be(bundle, icn_pos + (i * 4) + 6, 2) == local_id)
- {
- resource_id = pick_integer_be(bundle, icn_pos + (i * 4) + 8, 2);
- break;
- }
- }
- if (i >= icn_bundleentry_length)
- return err;
-
- /* fetch 32x32 icons (ICN#, icl4, icl8) */
- if (load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ICN# */ 0x49434E23, resource_id, 32, 32, 1, mac_palette_1bpp, true))
- {
- iconinfo->icon32x32_specified = 1;
-
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl4 */ 0x69636C34, resource_id, 32, 32, 4, mac_palette_4bpp, false);
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl8 */ 0x69636C38, resource_id, 32, 32, 8, mac_palette_8bpp, false);
- }
-
- /* fetch 16x16 icons (ics#, ics4, ics8) */
- if (load_icon((uint32_t *) iconinfo->icon16x16, resource_fork, resource_fork_length,
- /* ics# */ 0x69637323, resource_id, 16, 16, 1, mac_palette_1bpp, true))
- {
- iconinfo->icon16x16_specified = 1;
-
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics4 */ 0x69637334, resource_id, 32, 32, 4, mac_palette_4bpp, false);
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics8 */ 0x69637338, resource_id, 32, 32, 8, mac_palette_8bpp, false);
- }
-
- return err;
-}
-
-
-
-/*************************************
- *
- * File transfer suggestions
- *
- *************************************/
-
-static imgtoolerr_t mac_image_suggesttransfer(imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- file_category = (cat_info.rsrcLogicalSize > 0) ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
-*
-* MacOS Roman Conversion
-*
-*************************************/
-
-static const char32_t macos_roman_code_page[128] =
-{
- // 0x80 - 0x8F
- 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
- // 0x90 - 0x9F
- 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
- // 0xA0 - 0xAF
- 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
- // 0xB0 - 0xBF
- 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8,
- // 0xC0 - 0xCF
- 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
- // 0xD0 - 0xDF
- 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02,
- // 0xE0 - 0xEF
- 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
- // 0xF0 - 0xFF
- 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7
-};
-
-static imgtool::simple_charconverter charconverter_macos_roman(macos_roman_code_page);
-
-
-/*************************************
- *
- * Module population
- *
- *************************************/
-
-static void generic_mac_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(struct mac_l2_imgref); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct mac_iterator); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = ':'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- 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_CLOSE: /* info->close = mac_image_exit */; break;
- case IMGTOOLINFO_PTR_INFO: info->info = mac_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = mac_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = mac_image_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = mac_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = mac_image_readfile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = mac_image_listforks; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = mac_image_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = mac_image_setattrs; break;
- case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = mac_image_geticoninfo; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = mac_image_suggesttransfer; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_mac; break;
- case IMGTOOLINFO_PTR_CHARCONVERTER: info->charconverter = &charconverter_macos_roman; break;
- }
-}
-
-
-
-void mac_mfs_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_mfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac MFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = mfs_image_create; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = mfs_image_open; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = mac_image_writefile; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void mac_hfs_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_hfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac HFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = hfs_image_open; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/tools/imgtool/modules/macbin.cpp b/src/tools/imgtool/modules/macbin.cpp
deleted file mode 100644
index 30400dffdbb..00000000000
--- a/src/tools/imgtool/modules/macbin.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macbin.cpp
-
- MacBinary filter for use with Mac and ProDOS drivers
-
-*****************************************************************************
-
- MacBinary file format
-
- Offset Length Description
- ------ ------ -----------
- 0 1 [I] Magic byte (0x00)
- 1 64 [I] File name (Pascal String)
- 65 4 [I] File Type Code
- 69 4 [I] File Creator Code
- 73 1 [I] Finder Flags (bits 15-8)
- 74 1 [I] Magic byte (0x00)
- 75 2 [I] File Vertical Position
- 77 2 [I] File Horizontal Position
- 79 2 [I] Window/Folder ID
- 81 1 [I] Protected (bit 0)
- 82 1 [I] Magic byte (0x00)
- 83 4 [I] Data Fork Length
- 87 4 [I] Resource Fork Length
- 91 4 [I] Creation Date
- 95 4 [I] Last Modified Date
- 99 2 [I] "Get Info" comment length
- 101 1 [II] Finder Flags (bits 7-0)
- 102 4 [III] MacBinary III Signature 'mBIN'
- 106 1 [III] Script of Filename
- 107 1 [III] Extended Finder Flags
- 116 4 [II] Unpacked Length
- 120 2 [II] Secondary Header Length
- 122 1 [II] MacBinary II Version Number (II: 0x81, III: 0x82)
- 123 1 [II] Minimum Compatible MacBinary II Version Number (0x81)
- 124 2 [II] CRC of previous 124 bytes
-
- For more information, consult http://www.lazerware.com/formats/macbinary.html
-
- TODO: I believe that the script code is some sort of identifier identifying
- the character set used for the filename. If this is true, we are not
- handling that properly
-
-*****************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "macutil.h"
-
-
-
-static uint32_t pad128(uint32_t length)
-{
- if (length % 128)
- length += 128 - (length % 128);
- return length;
-}
-
-
-
-static imgtoolerr_t macbinary_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf)
-{
- static const uint32_t attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- uint8_t header[128];
- const char *basename;
-
- uint32_t type_code = 0x3F3F3F3F;
- uint32_t creator_code = 0x3F3F3F3F;
- uint16_t finder_flags = 0;
- uint16_t coord_x = 0;
- uint16_t coord_y = 0;
- uint16_t finder_folder = 0;
- uint8_t script_code = 0;
- uint8_t extended_flags = 0;
-
- uint32_t creation_time = 0;
- uint32_t lastmodified_time = 0;
- imgtool_attribute attr_values[10];
-
- // get the forks
- std::vector<imgtool::fork_entry> fork_entries;
- err = partition.list_file_forks(filename, fork_entries);
- if (err)
- return err;
-
- const imgtool::fork_entry *data_fork = nullptr;
- const imgtool::fork_entry *resource_fork = nullptr;
- for (const auto &entry : fork_entries)
- {
- switch (entry.type())
- {
- case imgtool::fork_entry::type_t::DATA:
- data_fork = &entry;
- break;
- case imgtool::fork_entry::type_t::RESOURCE:
- resource_fork = &entry;
- break;
- default:
- // do nothing
- break;
- }
- }
-
- /* get the attributes */
- err = partition.get_file_attributes(filename, attrs, attr_values);
- if (err && (ERRORCODE(err) != IMGTOOLERR_UNIMPLEMENTED))
- return err;
- if (err == IMGTOOLERR_SUCCESS)
- {
- creation_time = mac_setup_time(attr_values[0].t);
- lastmodified_time = mac_setup_time(attr_values[1].t);
- type_code = attr_values[2].i;
- creator_code = attr_values[3].i;
- finder_flags = attr_values[4].i;
- coord_x = attr_values[5].i;
- coord_y = attr_values[6].i;
- finder_folder = attr_values[7].i;
- script_code = attr_values[8].i;
- extended_flags = attr_values[9].i;
- }
-
- memset(header, 0, sizeof(header));
-
- /* place filename */
- basename = filename;
- while(basename[strlen(basename) + 1])
- basename += strlen(basename) + 1;
- pascal_from_c_string((unsigned char *) &header[1], 64, basename);
-
- place_integer_be(header, 65, 4, type_code);
- place_integer_be(header, 69, 4, creator_code);
- place_integer_be(header, 73, 1, (finder_flags >> 8) & 0xFF);
- place_integer_be(header, 75, 2, coord_x);
- place_integer_be(header, 77, 2, coord_y);
- place_integer_be(header, 79, 2, finder_folder);
- place_integer_be(header, 83, 4, data_fork ? data_fork->size() : 0);
- place_integer_be(header, 87, 4, resource_fork ? resource_fork->size() : 0);
- place_integer_be(header, 91, 4, creation_time);
- place_integer_be(header, 95, 4, lastmodified_time);
- place_integer_be(header, 101, 1, (finder_flags >> 0) & 0xFF);
- place_integer_be(header, 102, 4, 0x6D42494E);
- place_integer_be(header, 106, 1, script_code);
- place_integer_be(header, 107, 1, extended_flags);
- place_integer_be(header, 122, 1, 0x82);
- place_integer_be(header, 123, 1, 0x81);
- place_integer_be(header, 124, 2, ccitt_crc16(0, header, 124));
-
- destf.write(header, sizeof(header));
-
- if (data_fork)
- {
- err = partition.read_file(filename, "", destf, NULL);
- if (err)
- return err;
-
- destf.fill(0, pad128(data_fork->size()));
- }
-
- if (resource_fork)
- {
- err = partition.read_file(filename, "RESOURCE_FORK", destf, NULL);
- if (err)
- return err;
-
- destf.fill(0, pad128(resource_fork->size()));
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t write_fork(imgtool::partition &partition, const char *filename, const char *fork,
- imgtool::stream &sourcef, uint64_t pos, uint64_t fork_len, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool::stream::ptr mem_stream;
- size_t len;
-
- if (fork_len > 0)
- {
- mem_stream = imgtool::stream::open_mem(nullptr, 0);
- if (!mem_stream)
- return IMGTOOLERR_OUTOFMEMORY;
-
- sourcef.seek(pos, SEEK_SET);
- len = imgtool::stream::transfer(*mem_stream, sourcef, fork_len);
- if (len < fork_len)
- mem_stream->fill(0, fork_len);
-
- mem_stream->seek(0, SEEK_SET);
- err = partition.write_file(filename, fork, *mem_stream, opts, NULL);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t macbinary_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
-{
- static const uint32_t attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- imgtool::image *image = &partition.image();
- uint8_t header[128];
- uint32_t datafork_size;
- uint32_t resourcefork_size;
- uint64_t total_size;
- uint32_t creation_time;
- uint32_t lastmodified_time;
- //int version;
- imgtool_attribute attr_values[10];
-
- uint32_t type_code;
- uint32_t creator_code;
- uint16_t finder_flags;
- uint16_t coord_x;
- uint16_t coord_y;
- uint16_t finder_folder;
- uint8_t script_code = 0;
- uint8_t extended_flags = 0;
-
- /* read in the header */
- memset(header, 0, sizeof(header));
- sourcef.read(header, sizeof(header));
-
- /* check magic and zero fill bytes */
- if (header[0] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[74] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[82] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
-
- datafork_size = pick_integer_be(header, 83, 4);
- resourcefork_size = pick_integer_be(header, 87, 4);
- total_size = sourcef.size();
-
- /* size of a MacBinary header is always 128 bytes */
- if (total_size - pad128(datafork_size) - pad128(resourcefork_size) != 128)
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check filename length byte */
- if ((header[1] <= 0x00) || (header[1] > 0x3F))
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check the CRC */
- if (pick_integer_be(header, 124, 2) != ccitt_crc16(0, header, 124))
- {
- /* the CRC does not match; this file is MacBinary I */
- //version = 1;
- }
- else if (pick_integer_be(header, 102, 4) != 0x6D42494E)
- {
- /* did not see 'mBIN'; this file is MacBinary II */
- if (header[122] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 2;
- }
- else
- {
- /* we did see 'mBIN'; this file is MacBinary III */
- if (header[122] < 0x82)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 3;
- }
-
- type_code = pick_integer_be(header, 65, 4);
- creator_code = pick_integer_be(header, 69, 4);
- finder_flags = pick_integer_be(header, 73, 1) << 8;
- coord_x = pick_integer_be(header, 75, 2);
- coord_y = pick_integer_be(header, 77, 2);
- finder_folder = pick_integer_be(header, 79, 2);
- creation_time = pick_integer_be(header, 91, 4);
- lastmodified_time = pick_integer_be(header, 95, 4);
-
- if (image)
- {
- /* write out both forks */
- err = write_fork(partition, filename, "", sourcef, sizeof(header), datafork_size, opts);
- if (err)
- return err;
- err = write_fork(partition, filename, "RESOURCE_FORK", sourcef, sizeof(header) + pad128(datafork_size), resourcefork_size, opts);
- if (err)
- return err;
-
- /* set up attributes */
- attr_values[0].t = mac_crack_time(creation_time).to_time_t();
- attr_values[1].t = mac_crack_time(lastmodified_time).to_time_t();
- attr_values[2].i = type_code;
- attr_values[3].i = creator_code;
- attr_values[4].i = finder_flags;
- attr_values[5].i = coord_x;
- attr_values[6].i = coord_y;
- attr_values[7].i = finder_folder;
- attr_values[8].i = script_code;
- attr_values[9].i = extended_flags;
-
- err = partition.put_file_attributes(filename, attrs, attr_values);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-// this was completely broken - it was calling macbinary_writefile() with a nullptr partition
-#if 0
-static imgtoolerr_t macbinary_checkstream(imgtool::stream &stream, imgtool_suggestion_viability_t *viability)
-{
- imgtoolerr_t err;
-
- err = macbinary_writefile(NULL, NULL, NULL, stream, NULL);
- if (err == IMGTOOLERR_CORRUPTFILE)
- {
- /* the filter returned corrupt; this is not a valid file */
- *viability = SUGGESTION_END;
- err = IMGTOOLERR_SUCCESS;
- }
- else if (err == IMGTOOLERR_SUCCESS)
- {
- /* success; lets recommend this filter */
- *viability = SUGGESTION_RECOMMENDED;
- }
- return err;
-}
-#endif
-
-
-
-void filter_macbinary_getinfo(uint32_t state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "macbinary"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "MacBinary"; break;
- case FILTINFO_STR_EXTENSION: info->s = "bin"; break;
- case FILTINFO_PTR_READFILE: info->read_file = macbinary_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = macbinary_writefile; break;
- //case FILTINFO_PTR_CHECKSTREAM: info->check_stream = macbinary_checkstream; break;
- }
-}
diff --git a/src/tools/imgtool/modules/macutil.cpp b/src/tools/imgtool/modules/macutil.cpp
deleted file mode 100644
index 08c8b84989f..00000000000
--- a/src/tools/imgtool/modules/macutil.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.cpp
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#include "macutil.h"
-#include "timeconv.h"
-
-
-typedef util::arbitrary_clock<std::uint32_t, 1904, 1, 1, 0, 0, 0, std::ratio<1, 1> > classic_mac_clock;
-
-//-------------------------------------------------
-// mac_crack_time
-//-------------------------------------------------
-
-imgtool::datetime mac_crack_time(uint32_t t)
-{
- classic_mac_clock::duration d(t);
- std::chrono::time_point<classic_mac_clock> tp(d);
- return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, tp);
-}
-
-
-//-------------------------------------------------
-// mac_setup_time
-//-------------------------------------------------
-
-uint32_t mac_setup_time(const imgtool::datetime &t)
-{
- auto mac_time_point = classic_mac_clock::from_arbitrary_time_point(t.time_point());
- return mac_time_point.time_since_epoch().count();
-}
-
-
-//-------------------------------------------------
-// mac_setup_time
-//-------------------------------------------------
-
-uint32_t mac_setup_time(time_t t)
-{
- imgtool::datetime dt(imgtool::datetime::datetime_type::LOCAL, t);
- return mac_setup_time(dt);
-}
-
-
-//-------------------------------------------------
-// mac_time_now
-//-------------------------------------------------
-
-uint32_t mac_time_now(void)
-{
- imgtool::datetime dt = imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL);
- return mac_setup_time(dt);
-}
-
-
-//-------------------------------------------------
-// mac_identify_fork
-//-------------------------------------------------
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num)
-{
- if (!strcmp(fork_string, ""))
- *fork_num = MAC_FORK_DATA;
- else if (!strcmp(fork_string, "RESOURCE_FORK"))
- *fork_num = MAC_FORK_RESOURCE;
- else
- return IMGTOOLERR_FORKNOTFOUND;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- suggestions[0].viability = (file_category == MAC_FILECATEGORY_FORKED) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[0].filter = filter_macbinary_getinfo;
- suggestions[0].fork = NULL;
- suggestions[0].description = NULL;
-
- suggestions[1].viability = (file_category == MAC_FILECATEGORY_TEXT) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_eoln_getinfo;
- suggestions[1].fork = NULL;
- suggestions[1].description = NULL;
-
- suggestions[2].viability = (file_category == MAC_FILECATEGORY_DATA) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[2].filter = NULL;
- suggestions[2].fork = "";
- suggestions[2].description = "Raw (data fork)";
-
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- suggestions[3].fork = "RESOURCE_FORK";
- suggestions[3].description = "Raw (resource fork)";
-}
-
-
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring)
-{
- size_t cstring_len, i;
-
- cstring_len = strlen(cstring);
- pstring[0] = std::min(cstring_len, pstring_len - 1);
-
- for (i = 0; i < pstring[0]; i++)
- pstring[1 + i] = cstring[i];
- while(i < pstring_len - 1)
- pstring[1 + i++] = '\0';
-}
diff --git a/src/tools/imgtool/modules/macutil.h b/src/tools/imgtool/modules/macutil.h
deleted file mode 100644
index 0ab3315874b..00000000000
--- a/src/tools/imgtool/modules/macutil.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.h
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#ifndef MACUTIL_H
-#define MACUTIL_H
-
-#include "imgtool.h"
-
-enum mac_fork_t
-{
- MAC_FORK_DATA,
- MAC_FORK_RESOURCE
-};
-
-enum mac_filecategory_t
-{
- MAC_FILECATEGORY_DATA,
- MAC_FILECATEGORY_TEXT,
- MAC_FILECATEGORY_FORKED
-};
-
-
-/* converting Classic Mac OS time <==> Imgtool time */
-imgtool::datetime mac_crack_time(uint32_t t);
-uint32_t mac_setup_time(const imgtool::datetime &t);
-uint32_t mac_setup_time(time_t t);
-uint32_t mac_time_now(void);
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num);
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring);
-
-#endif /* MACUTIL_H */
diff --git a/src/tools/imgtool/modules/os9.cpp b/src/tools/imgtool/modules/os9.cpp
index cc016250c31..97fdcb9e209 100644
--- a/src/tools/imgtool/modules/os9.cpp
+++ b/src/tools/imgtool/modules/os9.cpp
@@ -8,13 +8,16 @@
****************************************************************************/
-#include <time.h>
-
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/coco_dsk.h"
#include "iflopimg.h"
+#include "formats/coco_dsk.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <ctime>
+
enum creation_policy_t
{
CREATE_NONE,
@@ -44,7 +47,7 @@ struct os9_diskinfo
unsigned int octal_track_density : 1;
char name[33];
- uint8_t *allocation_bitmap;
+ uint8_t allocation_bitmap[65536];
};
@@ -96,20 +99,13 @@ static void pick_string(const void *ptr, size_t offset, size_t length, char *des
-static void place_string(void *ptr, size_t offset, size_t length, const char *s)
+static void place_string(uint8_t *bptr, size_t length, const char *s)
{
- size_t i;
- uint8_t b;
- uint8_t *bptr;
-
- bptr = (uint8_t *) ptr;
- bptr += offset;
-
bptr[0] = 0x80;
- for (i = 0; s[i] && (i < length); i++)
+ for (size_t i = 0; s[i] && (i < length); i++)
{
- b = ((uint8_t) s[i]) & 0x7F;
+ uint8_t b = ((uint8_t) s[i]) & 0x7F;
if (s[i+1] == '\0')
b |= 0x80;
bptr[i] = b;
@@ -228,7 +224,7 @@ static int os9_interpret_dirent(void *entry, char **filename, uint32_t *lsn, int
entry_b[i] &= 0x7F;
entry_b[i+1] = '\0';
- *lsn = pick_integer_be(entry, 29, 3);
+ *lsn = get_u24be((uint8_t *) &entry_b[29]);
if (strcmp(entry_b, ".") && strcmp(entry_b, ".."))
*filename = entry_b;
return *filename != NULL;
@@ -257,10 +253,10 @@ static imgtoolerr_t os9_decode_file_header(imgtool::image &image,
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);
+ attributes = header[0];
+ info->owner_id = get_u16be(&header[1]);
+ info->link_count = header[8];
+ info->file_size = get_u32be(&header[9]);
info->directory = (attributes & 0x80) ? 1 : 0;
info->non_sharable = (attributes & 0x40) ? 1 : 0;
info->public_execute = (attributes & 0x20) ? 1 : 0;
@@ -275,11 +271,11 @@ static imgtoolerr_t os9_decode_file_header(imgtool::image &image,
/* read all sector map entries */
max_entries = (disk_info->sector_size - 16) / 5;
- max_entries = (std::min<std::size_t>)(max_entries, ARRAY_LENGTH(info->sector_map) - 1);
+ max_entries = (std::min<std::size_t>)(max_entries, std::size(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);
+ lsn = get_u24be(&header[16 + (i * 5) + 0]);
+ count = get_u16be(&header[16 + (i * 5) + 3]);
if (count <= 0)
break;
@@ -393,7 +389,7 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
/* 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)))
+ while((lsn < current_lsn_count) && (sector_map_length < std::size(file_info->sector_map)))
{
if (file_info->sector_map[sector_map_length].count == 0)
return os9_corrupt_file_error(file_info);
@@ -434,7 +430,7 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
{
file_info->sector_map[sector_map_length - 1].count++;
}
- else if (sector_map_length >= ARRAY_LENGTH(file_info->sector_map))
+ else if (sector_map_length >= std::size(file_info->sector_map))
{
return IMGTOOLERR_NOSPACE;
}
@@ -456,15 +452,15 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
return err;
file_info->file_size = new_size;
- place_integer_be(header, 9, 4, file_info->file_size);
+ put_u32be(&header[9], file_info->file_size);
/* do we have to write the sector map? */
if (sector_map_length >= 0)
{
- for (i = 0; i < (std::min<std::size_t>)(sector_map_length + 1, ARRAY_LENGTH(file_info->sector_map)); i++)
+ for (i = 0; i < (std::min<std::size_t>)(sector_map_length + 1, std::size(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);
+ put_u24be(&header[16 + (i * 5) + 0], file_info->sector_map[i].lsn);
+ put_u16be(&header[16 + (i * 5) + 3], file_info->sector_map[i].count);
}
}
@@ -567,7 +563,7 @@ static imgtoolerr_t os9_lookup_path(imgtool::image &img, const char *path,
/* write the file */
memset(block, 0, sizeof(block));
- place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00));
+ block[0] = 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00);
err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block));
if (err)
goto done;
@@ -585,8 +581,8 @@ static imgtoolerr_t os9_lookup_path(imgtool::image &img, const char *path,
/* now prepare the directory entry */
memset(entry, 0, sizeof(entry));
- place_string(entry, 0, 28, path);
- place_integer_be(entry, 29, 3, allocated_lsn);
+ place_string(&entry[0], 28, path);
+ put_u24be(&entry[29], allocated_lsn);
/* now write the directory entry */
entry_index = dir_size;
@@ -638,20 +634,19 @@ static imgtoolerr_t os9_diskimage_open(imgtool::image &image, imgtool::stream::p
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->total_sectors = get_u24be(&header[ 0]);
+ track_size_in_sectors = header[ 3];
+ info->allocation_bitmap_bytes = get_u16be(&header[ 4]);
+ info->cluster_size = get_u16be(&header[ 6]);
+ info->root_dir_lsn = get_u24be(&header[ 8]);
+ info->owner_id = get_u16be(&header[ 11]);
+// attributes = header[ 13];
+ info->disk_id = get_u16be(&header[ 14]);
+ info->format_flags = header[ 16];
+ info->sectors_per_track = get_u16be(&header[ 17]);
+ info->bootstrap_lsn = get_u24be(&header[ 21]);
+ info->bootstrap_size = get_u16be(&header[ 24]);
+ info->sector_size = get_u16be(&header[104]);
info->sides = (info->format_flags & 0x01) ? 2 : 1;
info->double_density = (info->format_flags & 0x02) ? 1 : 0;
@@ -670,10 +665,7 @@ static imgtoolerr_t os9_diskimage_open(imgtool::image &image, imgtool::stream::p
return IMGTOOLERR_CORRUPTIMAGE;
/* is the allocation bitmap too big? */
- info->allocation_bitmap = (uint8_t*)image.malloc(info->allocation_bitmap_bytes);
- if (!info->allocation_bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(info->allocation_bitmap, 0, info->allocation_bitmap_bytes);
+ memset(&info->allocation_bitmap[0], 0, info->allocation_bitmap_bytes);
/* sectors per track and track size don't jive? */
if (info->sectors_per_track != track_size_in_sectors)
@@ -747,30 +739,30 @@ static imgtoolerr_t os9_diskimage_create(imgtool::image &img, imgtool::stream::p
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);
+ put_u24be(&header[ 0], heads * tracks * sectors);
+ header[ 3] = sectors;
+ put_u16be(&header[ 4], (allocation_bitmap_bits + 7) / 8);
+ put_u16be(&header[ 6], cluster_size);
+ put_u24be(&header[ 8], 1 + allocation_bitmap_lsns);
+ put_u16be(&header[ 11], owner_id);
+ header[ 13] = attributes;
+ put_u16be(&header[ 14], disk_id);
+ header[ 16] = format_flags;
+ put_u16be(&header[ 17], sectors);
+ place_string(&header[ 31], 32, title);
+ put_u16be(&header[103], 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 */
+ header[0x3f+0x00] = 1; /* device class */
+ header[0x3f+0x01] = 1; /* drive number */
+ header[0x3f+0x03] = 0x20; /* device type */
+ header[0x3f+0x04] = 1; /* density capability */
+ put_u16be(&header[0x3f+0x05], tracks); /* number of tracks */
+ header[0x3f+0x07] = heads; /* number of sides */
+ put_u16be(&header[0x3f+0x09], sectors); /* sectors per track */
+ put_u16be(&header[0x3f+0x0b], sectors); /* sectors on track zero */
+ header[0x3f+0x0d] = 3; /* sector interleave factor */
+ header[0x3f+0x0e] = 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)
@@ -824,8 +816,8 @@ static imgtoolerr_t os9_diskimage_create(imgtool::image &img, imgtool::stream::p
header[0x0D] = (uint8_t) (ltime->tm_year % 100);
header[0x0E] = (uint8_t) ltime->tm_mon;
header[0x0F] = (uint8_t) ltime->tm_mday;
- place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1);
- place_integer_be(&header[0], 0x13, 2, 8);
+ put_u24be(&header[0x10], 1 + allocation_bitmap_lsns + 1);
+ put_u16be(&header[0x13], 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)
@@ -929,7 +921,7 @@ static imgtoolerr_t os9_diskimage_nextenum(imgtool::directory &enumeration, imgt
}
/* 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))
+ if (!strcmp(filename, ".") && (get_u24be(&dir_entry[29]) != os9enum->dir_info.lsn))
{
imgtool_warn("Directory \".\" does not point back to same directory");
}
@@ -946,14 +938,14 @@ static imgtoolerr_t os9_diskimage_nextenum(imgtool::directory &enumeration, imgt
while(!filename[0] || !strcmp(filename, ".") || !strcmp(filename, ".."));
/* read file attributes */
- lsn = pick_integer_be(dir_entry, 29, 3);
+ lsn = get_u24be(&dir_entry[29]);
err = os9_decode_file_header(enumeration.image(), 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",
+ snprintf(ent.filename, std::size(ent.filename), "%s", filename);
+ snprintf(ent.attr, std::size(ent.attr), "%c%c%c%c%c%c%c%c",
file_info.directory ? 'd' : '-',
file_info.non_sharable ? 's' : '-',
file_info.public_execute ? 'x' : '-',
@@ -1143,7 +1135,7 @@ static imgtoolerr_t os9_diskimage_delete(imgtool::partition &partition, const ch
if (err)
return err;
- for (i = 0; (i < ARRAY_LENGTH(file_info.sector_map)) && file_info.sector_map[i].count; i++)
+ for (i = 0; (i < std::size(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++)
@@ -1185,10 +1177,10 @@ static imgtoolerr_t os9_diskimage_createdir(imgtool::partition &partition, const
/* 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);
+ place_string(&dir_data[ 0], 32, "..");
+ put_u24be(&dir_data[29], parent_lsn);
+ place_string(&dir_data[32], 32, ".");
+ put_u24be(&dir_data[61], file_info.lsn);
err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data));
if (err)
diff --git a/src/tools/imgtool/modules/pc_flop.cpp b/src/tools/imgtool/modules/pc_flop.cpp
index 211b7f7b938..6a242d16abf 100644
--- a/src/tools/imgtool/modules/pc_flop.cpp
+++ b/src/tools/imgtool/modules/pc_flop.cpp
@@ -9,11 +9,14 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/pc_dsk.h"
#include "fat.h"
#include "iflopimg.h"
+#include "formats/pc_dsk_legacy.h"
+
+#include "multibyte.h"
+#include "opresolv.h"
+
#define FAT_SECLEN 512
@@ -31,10 +34,10 @@ static imgtoolerr_t fat_image_create(imgtool::image &image, imgtool::stream::ptr
/* set up just enough of a boot sector to specify geometry */
memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 24, 2, sectors);
- place_integer_le(buffer, 26, 2, heads);
- place_integer_le(buffer, 19, 2, (uint16_t) (((uint64_t) tracks * heads * sectors) >> 0));
- place_integer_le(buffer, 32, 4, (uint16_t) (((uint64_t) tracks * heads * sectors) >> 16));
+ put_u16le(&buffer[24], sectors);
+ put_u16le(&buffer[26], heads);
+ put_u16le(&buffer[19], uint16_t((uint64_t(tracks) * heads * sectors) >> 0));
+ put_u32le(&buffer[32], uint16_t((uint64_t(tracks) * heads * sectors) >> 16));
err = image.write_block(0, buffer);
if (err)
goto done;
@@ -44,7 +47,7 @@ static imgtoolerr_t fat_image_create(imgtool::image &image, imgtool::stream::ptr
imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_PARTITION);
/* actually create the partition */
- err = fat_partition_create(image, 0, ((uint64_t) tracks) * heads * sectors);
+ err = fat_partition_create(image, 0, uint64_t(tracks) * heads * sectors);
if (err)
goto done;
@@ -64,11 +67,11 @@ static imgtoolerr_t fat_image_get_geometry(imgtool::image &image, uint32_t *trac
if (err)
return err;
- total_sectors = pick_integer_le(buffer, 19, 2)
- | (pick_integer_le(buffer, 32, 4) << 16);
+ total_sectors = get_u16le(&buffer[19])
+ | uint64_t(get_u32le(&buffer[32]) << 16);
- *sectors = pick_integer_le(buffer, 24, 2);
- *heads = pick_integer_le(buffer, 26, 2);
+ *sectors = get_u16le(&buffer[24]);
+ *heads = get_u16le(&buffer[26]);
*tracks = total_sectors / *heads / *sectors;
return IMGTOOLERR_SUCCESS;
}
diff --git a/src/tools/imgtool/modules/pc_hard.cpp b/src/tools/imgtool/modules/pc_hard.cpp
index c04ad33cce6..353a6b5dac5 100644
--- a/src/tools/imgtool/modules/pc_hard.cpp
+++ b/src/tools/imgtool/modules/pc_hard.cpp
@@ -50,9 +50,11 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
#include "imghd.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
#define FAT_SECLEN 512
OPTION_GUIDE_START( pc_chd_create_optionguide )
@@ -103,15 +105,12 @@ static pc_chd_image_info *pc_chd_get_image_info(imgtool::image &image)
static void pc_chd_locate_block(imgtool::image &image, uint64_t block, uint32_t *cylinder, uint32_t *head, uint32_t *sector)
{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
+ pc_chd_image_info *info = pc_chd_get_image_info(image);
+ const auto &hd_info = imghd_get_header(&info->hard_disk);
- *sector = block % hd_info->sectors;
- *head = (block / hd_info->sectors) % hd_info->heads;
- *cylinder = block / hd_info->sectors / hd_info->heads;
+ *sector = block % hd_info.sectors;
+ *head = (block / hd_info.sectors) % hd_info.heads;
+ *cylinder = block / hd_info.sectors / hd_info.heads;
}
@@ -168,16 +167,16 @@ static imgtoolerr_t pc_chd_partition_create(imgtool::image &image, int partition
/* fill out the partition entry */
partition_entry = &header_block[446 + (partition_index * 16)];
- place_integer_le(partition_entry, 0, 1, 0x80);
- place_integer_le(partition_entry, 1, 1, first_head);
- place_integer_le(partition_entry, 2, 1, ((first_sector & 0x3F) | (first_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 3, 1, first_cylinder);
- place_integer_le(partition_entry, 4, 1, partition_type);
- place_integer_le(partition_entry, 5, 1, last_head);
- place_integer_le(partition_entry, 6, 1, ((last_sector & 0x3F) | (last_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 7, 1, last_cylinder);
- place_integer_le(partition_entry, 8, 4, first_block);
- place_integer_le(partition_entry, 12, 4, block_count);
+ partition_entry[0] = 0x80;
+ partition_entry[1] = first_head;
+ partition_entry[2] = ((first_sector & 0x3F) | (first_cylinder >> 8 << 2));
+ partition_entry[3] = first_cylinder;
+ partition_entry[4] = partition_type;
+ partition_entry[5] = last_head;
+ partition_entry[6] = ((last_sector & 0x3F) | (last_cylinder >> 8 << 2));
+ partition_entry[7] = last_cylinder;
+ put_u32le(&partition_entry[ 8], first_block);
+ put_u32le(&partition_entry[12], block_count);
/* write the partition header */
err = image.write_block(0, header_block);
@@ -193,7 +192,6 @@ done:
static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
{
imgtoolerr_t err;
- int i;
const uint8_t *partition_info;
pc_chd_image_info *info;
uint8_t buffer[FAT_SECLEN];
@@ -209,7 +207,7 @@ static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
if ((buffer[510] != 0x55) || (buffer[511] != 0xAA))
return IMGTOOLERR_CORRUPTIMAGE;
- for (i = 0; i < ARRAY_LENGTH(info->partitions); i++)
+ for (int i = 0; i < std::size(info->partitions); i++)
{
partition_info = &buffer[446 + i * 16];
@@ -221,8 +219,8 @@ static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
info->partitions[i].ending_track = ((partition_info[6] << 2) & 0xFF00) | partition_info[7];
info->partitions[i].ending_sector = partition_info[6] & 0x3F;
- info->partitions[i].sector_index = pick_integer_le(partition_info, 8, 4);
- info->partitions[i].total_sectors = pick_integer_le(partition_info, 12, 4);
+ info->partitions[i].sector_index = get_u32le(&partition_info[ 8]);
+ info->partitions[i].total_sectors = get_u32le(&partition_info[12]);
if (info->partitions[i].starting_track > info->partitions[i].ending_track)
return IMGTOOLERR_CORRUPTIMAGE;
@@ -310,15 +308,12 @@ static void pc_chd_image_close(imgtool::image &image)
static imgtoolerr_t pc_chd_image_get_geometry(imgtool::image &image, uint32_t *tracks, uint32_t *heads, uint32_t *sectors)
{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
+ pc_chd_image_info *info = pc_chd_get_image_info(image);
+ const auto &hd_info = imghd_get_header(&info->hard_disk);
- *tracks = hd_info->cylinders;
- *heads = hd_info->heads;
- *sectors = hd_info->sectors;
+ *tracks = hd_info.cylinders;
+ *heads = hd_info.heads;
+ *sectors = hd_info.sectors;
return IMGTOOLERR_SUCCESS;
}
@@ -327,13 +322,11 @@ static imgtoolerr_t pc_chd_image_get_geometry(imgtool::image &image, uint32_t *t
static uint32_t pc_chd_calc_lbasector(pc_chd_image_info &info, uint32_t track, uint32_t head, uint32_t sector)
{
uint32_t lbasector;
- const hard_disk_info *hd_info;
-
- hd_info = imghd_get_header(&info.hard_disk);
+ const auto &hd_info = imghd_get_header(&info.hard_disk);
lbasector = track;
- lbasector *= hd_info->heads;
+ lbasector *= hd_info.heads;
lbasector += head;
- lbasector *= hd_info->sectors;
+ lbasector *= hd_info.sectors;
lbasector += sector;
return lbasector;
}
@@ -345,7 +338,7 @@ static imgtoolerr_t pc_chd_image_readsector(imgtool::image &image, uint32_t trac
pc_chd_image_info *info = pc_chd_get_image_info(image);
// get the sector size and resize the buffer
- uint32_t sector_size = imghd_get_header(&info->hard_disk)->sectorbytes;
+ uint32_t sector_size = imghd_get_header(&info->hard_disk).sectorbytes;
try { buffer.resize(sector_size); }
catch (std::bad_alloc const &) { return IMGTOOLERR_OUTOFMEMORY; }
diff --git a/src/tools/imgtool/modules/prodos.cpp b/src/tools/imgtool/modules/prodos.cpp
deleted file mode 100644
index 6db41ae529b..00000000000
--- a/src/tools/imgtool/modules/prodos.cpp
+++ /dev/null
@@ -1,2267 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- prodos.cpp
-
- Apple II ProDOS disk images
-
-*****************************************************************************
-
- Notes:
- - ProDOS disks are split into 512 byte blocks.
-
- ProDOS directory structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 ???
- 2 2 Next block (0 if end)
- 4 39 Directory Entry
- 43 39 Directory Entry
- ...
- 472 39 Directory Entry
- 511 1 ???
-
-
- ProDOS directory entry structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 7-4)
- 10 - Seedling File (1 block)
- 20 - Sapling File (2-256 blocks)
- 30 - Tree File (257-32768 blocks)
- 40 - Pascal Areas on ProFile HDs (???)
- 50 - GS/OS Extended File (data and rsrc fork)
- E0 - Subdirectory Header
- F0 - Volume Header
- 1 15 File name (NUL padded)
- 16 1 File type
- 17 2 Key pointer
- 19 2 Blocks used
- 21 3 File size
- 24 4 Creation date
- 28 1 ProDOS version that created the file
- 29 1 Minimum ProDOS version needed to read the file
- 30 1 Access byte
- 31 2 Auxilary file type
- 33 4 Last modified date
- 37 2 Header pointer
-
-
- In "seedling files", the key pointer points to a single block that is the
- whole file. In "sapling files", the key pointer points to an index block
- that contains 256 2-byte index pointers that point to the actual blocks of
- the files. These 2-byte values are not contiguous; the low order byte is
- in the first half of the block, and the high order byte is in the second
- half of the block. In "tree files", the key pointer points to an index
- block of index blocks.
-
- ProDOS dates are 32-bit little endian values
-
- bits 0- 4 Day
- bits 5- 8 Month (0-11)
- bits 9-15 Year (0-49 is 2000-2049, 50-99 is 1950-1999)
- bits 16-21 Minute
- bits 24-28 Hour
-
-
- ProDOS directory and volume headers have this information:
-
- Offset Length Description
- ------ ------ -----------
- 31 1 Length of the entry; generally is 39
- 32 1 Number of entries per block; generally is 13
- 33 2 Active entry count in directory
- 35 2 Volume bitmap block number
- 37 2 Total blocks on volume
-
- GS/OS Extended Files (storage type $5) point to an extended key block that
- contains information about the two forks. The first half of the extended
- key block contains info about the data form, and the second half the
- resource fork. Both sides have the following format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 3-0, unlike the directory entry)
- 1 2 Key pointer
- 3 2 Blocks used
- 5 3 File size
- 8 1 Size of secondary info #1 (must be 18 to be valid)
- 9 1 Secondary info #1 type (1=FInfo 2=xFInfo)
- 10 16 FInfo or xFInfo
- 26 1 Size of secondary info #2 (must be 18 to be valid)
- 27 1 Secondary info #2 type (1=FInfo 2=xFInfo)
- 28 16 FInfo or xFInfo
-
- FInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 4 File type
- 4 4 File creator
- 8 2 Finder flags
- 10 2 X Coordinate
- 12 2 Y Coordinate
- 14 2 Finder folder
-
- xFInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Icon ID
- 2 6 Reserved
- 8 1 Script Code
- 9 1 Extended flags
- 10 2 Comment ID
- 12 4 Put Away Directory
-
-
- For more info, consult ProDOS technical note #25
- (http://web.pdx.edu/~heiss/technotes/pdos/tn.pdos.25.html)
-
-*****************************************************************************/
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/ap2_dsk.h"
-#include "formats/ap_dsk35.h"
-#include "iflopimg.h"
-#include "macutil.h"
-
-#define ROOTDIR_BLOCK 2
-#define BLOCK_SIZE 512
-
-struct prodos_diskinfo
-{
- imgtoolerr_t (*load_block)(imgtool::image &image, int block, void *buffer);
- imgtoolerr_t (*save_block)(imgtool::image &image, int block, const void *buffer);
- uint8_t dirent_size;
- uint8_t dirents_per_block;
- uint16_t volume_bitmap_block;
- uint16_t total_blocks;
-};
-
-struct prodos_direnum
-{
- uint32_t block;
- uint32_t index;
- uint8_t block_data[BLOCK_SIZE];
-};
-
-struct prodos_dirent
-{
- char filename[16];
- uint8_t storage_type;
- uint16_t extkey_pointer;
- uint16_t key_pointer[2];
- uint32_t filesize[2];
- int depth[2];
- uint32_t lastmodified_time;
- uint32_t creation_time;
-
- /* FInfo */
- uint32_t file_type;
- uint32_t file_creator;
- uint16_t finder_flags;
- uint16_t coord_x;
- uint16_t coord_y;
- uint16_t finder_folder;
-
- /* xFInfo */
- uint16_t icon_id;
- uint8_t script_code;
- uint8_t extended_flags;
- uint16_t comment_id;
- uint32_t putaway_directory;
-};
-
-enum creation_policy_t
-{
- CREATE_NONE,
- CREATE_FILE,
- CREATE_DIR
-};
-
-
-
-static imgtool::datetime prodos_crack_time(uint32_t prodos_time)
-{
- util::arbitrary_datetime dt;
- dt.second = 0;
- dt.minute = ((prodos_time >> 16) & 0x3F);
- dt.hour = ((prodos_time >> 24) & 0x1F);
- dt.day_of_month = ((prodos_time >> 0) & 0x1F);
- dt.month = ((prodos_time >> 5) & 0x0F) + 1;
- dt.year = ((prodos_time >> 9) & 0x7F) + 1900;
- if (dt.year <= 1949)
- dt.year += 100;
-
- return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, dt);
-}
-
-
-
-static uint32_t prodos_setup_time(time_t ansi_time)
-{
- struct tm t;
- uint32_t result = 0;
-
- t = *localtime(&ansi_time);
- if ((t.tm_year >= 100) && (t.tm_year <= 149))
- t.tm_year -= 100;
-
- result |= (((uint32_t) t.tm_min) & 0x003F) << 16;
- result |= (((uint32_t) t.tm_hour) & 0x001F) << 24;
- result |= (((uint32_t) t.tm_mday) & 0x001F) << 0;
- result |= (((uint32_t) t.tm_mon) & 0x000F) << 5;
- result |= (((uint32_t) t.tm_year) & 0x007F) << 9;
- return result;
-}
-
-
-
-static uint32_t prodos_time_now(void)
-{
- time_t now;
- time(&now);
- return prodos_setup_time(now);
-}
-
-
-
-static int is_file_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F))
- || ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_normalfile_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F));
-}
-
-
-
-static int is_extendedfile_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_dir_storagetype(uint8_t storage_type)
-{
- return (storage_type >= 0xE0) && (storage_type <= 0xEF);
-}
-
-
-
-static prodos_diskinfo *get_prodos_info(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = (prodos_diskinfo *) imgtool_floppy_extrabytes(image);
- return info;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static void prodos_find_block_525(imgtool::image &image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector1, uint32_t *sector2)
-{
- static const uint8_t skewing[] =
- {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F
- };
-
- block *= 2;
-
- *track = block / APPLE2_SECTOR_COUNT;
- *head = 0;
- *sector1 = skewing[block % APPLE2_SECTOR_COUNT + 0];
- *sector2 = skewing[block % APPLE2_SECTOR_COUNT + 1];
-}
-
-
-
-static imgtoolerr_t prodos_load_block_525(imgtool::image &image,
- int block, void *buffer)
-{
- floperr_t ferr;
- uint32_t track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((uint8_t *) buffer) + 0, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((uint8_t *) buffer) + 256, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_525(imgtool::image &image,
- int block, const void *buffer)
-{
- floperr_t ferr;
- uint32_t track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((const uint8_t *) buffer) + 0, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((const uint8_t *) buffer) + 256, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_525(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_525;
- info->save_block = prodos_save_block_525;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_find_block_35(imgtool::image &image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector)
-{
- int sides = 2;
-
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(image), *track) * sides))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(image), (*track)++) * sides);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_load_block_35(imgtool::image &image,
- int block, void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_35(imgtool::image &image,
- int block, const void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_35(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_35;
- info->save_block = prodos_save_block_35;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_block(imgtool::image &image,
- int block, void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->load_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_save_block(imgtool::image &image,
- int block, const void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->save_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_clear_block(imgtool::image &image, int block)
-{
- uint8_t buffer[BLOCK_SIZE];
- memset(buffer, 0, sizeof(buffer));
- return prodos_save_block(image, block, buffer);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_open(imgtool::image &image)
-{
- imgtoolerr_t err;
- uint8_t buffer[BLOCK_SIZE];
- prodos_diskinfo *di;
- const uint8_t *ent;
-
- di = get_prodos_info(image);
-
- /* specify defaults */
- di->dirent_size = 39;
- di->dirents_per_block = 13;
-
- /* load the first block, hoping that the volume header is first */
- err = prodos_load_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- ent = &buffer[4];
-
- /* did we find the volume header? */
- if ((ent[0] & 0xF0) == 0xF0)
- {
- di->dirent_size = pick_integer_le(ent, 31, 1);
- di->dirents_per_block = pick_integer_le(ent, 32, 1);
- di->volume_bitmap_block = pick_integer_le(ent, 35, 2);
- di->total_blocks = pick_integer_le(ent, 37, 2);
- }
-
- /* sanity check these values */
- if (di->dirent_size < 39)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->dirents_per_block * di->dirent_size >= BLOCK_SIZE)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->volume_bitmap_block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_525(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_35(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_volume_bitmap(imgtool::image &image, uint8_t **bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t *alloc_bitmap;
- uint32_t bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
- alloc_bitmap = (uint8_t*)malloc(bitmap_blocks * BLOCK_SIZE);
- if (!alloc_bitmap)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_load_block(image, di->volume_bitmap_block + i,
- &alloc_bitmap[i * BLOCK_SIZE]);
- if (err)
- goto done;
- }
-
- err = IMGTOOLERR_SUCCESS;
-
-done:
- if (err && alloc_bitmap)
- {
- free(alloc_bitmap);
- alloc_bitmap = NULL;
- }
- *bitmap = alloc_bitmap;
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_save_volume_bitmap(imgtool::image &image, const uint8_t *bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint32_t bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_save_block(image, di->volume_bitmap_block + i,
- &bitmap[i * BLOCK_SIZE]);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_set_volume_bitmap_bit(uint8_t *buffer, uint16_t block, int value)
-{
- uint8_t mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- if (value)
- *buffer |= mask;
- else
- *buffer &= ~mask;
-}
-
-
-
-static int prodos_get_volume_bitmap_bit(const uint8_t *buffer, uint16_t block)
-{
- uint8_t mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- return (*buffer & mask) ? 1 : 0;
-}
-
-
-
-static imgtoolerr_t prodos_alloc_block(imgtool::image &image, uint8_t *bitmap,
- uint16_t *block)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- prodos_diskinfo *di;
- uint16_t bitmap_blocks, i;
- uint8_t *alloc_bitmap = NULL;
-
- di = get_prodos_info(image);
- *block = 0;
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- if (!bitmap)
- {
- err = prodos_load_volume_bitmap(image, &alloc_bitmap);
- if (err)
- goto done;
- bitmap = alloc_bitmap;
- }
-
- for (i = (di->volume_bitmap_block + bitmap_blocks); i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- {
- prodos_set_volume_bitmap_bit(bitmap, i, 1);
- *block = i;
- break;
- }
- }
-
- if (*block > 0)
- {
- if (alloc_bitmap)
- {
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
- }
- else
- {
- err = IMGTOOLERR_NOSPACE;
- }
-
-done:
- if (err)
- *block = 0;
- if (alloc_bitmap)
- free(alloc_bitmap);
- return err;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_create(imgtool::image &image, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- uint32_t heads, tracks, sectors, sector_bytes;
- uint32_t dirent_size, volume_bitmap_block, i;
- uint32_t volume_bitmap_block_count, total_blocks;
- uint8_t buffer[BLOCK_SIZE];
-
- heads = opts->lookup_int('H');
- tracks = opts->lookup_int('T');
- sectors = opts->lookup_int('S');
- sector_bytes = opts->lookup_int('L');
-
- dirent_size = 39;
- volume_bitmap_block = 6;
- total_blocks = tracks * heads * sectors * sector_bytes / BLOCK_SIZE;
- volume_bitmap_block_count = (total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- /* prepare initial dir block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 4 + 0, 1, 0xF0);
- place_integer_le(buffer, 4 + 31, 1, dirent_size);
- place_integer_le(buffer, 4 + 32, 1, BLOCK_SIZE / dirent_size);
- place_integer_le(buffer, 4 + 35, 2, volume_bitmap_block);
- place_integer_le(buffer, 4 + 37, 2, total_blocks);
-
- err = prodos_save_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- /* setup volume bitmap */
- memset(buffer, 0, sizeof(buffer));
- for (i = 0; i < (volume_bitmap_block + volume_bitmap_block_count); i++)
- prodos_set_volume_bitmap_bit(buffer, i, 1);
- prodos_save_block(image, volume_bitmap_block, buffer);
-
- /* and finally open the image */
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_525(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_35(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_enum_seek(imgtool::image &image,
- prodos_direnum *appleenum, uint32_t block, uint32_t index)
-{
- imgtoolerr_t err;
- uint8_t buffer[BLOCK_SIZE];
-
- if (appleenum->block != block)
- {
- if (block != 0)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
- memcpy(appleenum->block_data, buffer, sizeof(buffer));
- }
- appleenum->block = block;
- }
-
- appleenum->index = index;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static uint8_t *next_info_block(uint8_t *buffer, size_t *position)
-{
- size_t side = *position & 0x100;
- size_t subpos = *position & 0x0FF;
- uint8_t *result;
-
- if (subpos < 8)
- {
- subpos = 8;
- *position = side + subpos;
- }
-
- while((buffer[side + subpos] == 0x00) || (subpos + buffer[side + subpos] > 0x100))
- {
- if (side)
- return NULL;
-
- side = 0x100;
- subpos = 8;
- }
-
- result = &buffer[side + subpos];
- subpos += *result;
- *position = side + subpos;
- return result;
-}
-
-
-
-static uint8_t *alloc_info_block(uint8_t *buffer, size_t block_size, uint8_t block_type)
-{
- size_t position = 0;
- size_t side;
- size_t subpos;
- uint8_t *result;
-
- while(next_info_block(buffer, &position))
- ;
-
- side = position & 0x100;
- subpos = position & 0x0FF;
-
- if ((subpos + block_size) > 0x100)
- return NULL;
-
- result = &buffer[side + subpos];
- *(result++) = (uint8_t) block_size;
- *(result++) = block_type;
- memset(result, 0, block_size - 2);
- return result;
-}
-
-
-
-static imgtoolerr_t prodos_get_next_dirent(imgtool::image &image,
- prodos_direnum *appleenum, prodos_dirent &ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- size_t finfo_offset;
- uint32_t next_block, next_index;
- uint32_t offset;
- uint8_t buffer[BLOCK_SIZE];
- const uint8_t *info_ptr;
- int fork_num;
-
- di = get_prodos_info(image);
- memset(&ent, 0, sizeof(ent));
-
- /* have we hit the end of the file? */
- if (appleenum->block == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* populate the resulting dirent */
- offset = appleenum->index * di->dirent_size + 4;
- ent.storage_type = appleenum->block_data[offset + 0];
- memcpy(ent.filename, &appleenum->block_data[offset + 1], 15);
- ent.filename[15] = '\0';
- ent.creation_time = pick_integer_le(appleenum->block_data, offset + 24, 4);
- ent.lastmodified_time = pick_integer_le(appleenum->block_data, offset + 33, 4);
- ent.file_type = 0x3F3F3F3F;
- ent.file_creator = 0x3F3F3F3F;
- ent.finder_flags = 0;
- ent.coord_x = 0;
- ent.coord_y = 0;
- ent.finder_folder = 0;
- ent.icon_id = 0;
- ent.script_code = 0;
- ent.extended_flags = 0;
- ent.comment_id = 0;
- ent.putaway_directory = 0;
-
- if (is_extendedfile_storagetype(ent.storage_type))
- {
- /* this is a ProDOS extended file; we need to get the extended info
- * block */
- ent.extkey_pointer = pick_integer_le(appleenum->block_data, offset + 17, 2);
-
- err = prodos_load_block(image, ent.extkey_pointer, buffer);
- if (err)
- return err;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- ent.key_pointer[fork_num] = pick_integer_le(buffer, 1 + (fork_num * 256), 2);
- ent.filesize[fork_num] = pick_integer_le(buffer, 5 + (fork_num * 256), 3);
- ent.depth[fork_num] = buffer[fork_num * 256] & 0x0F;
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- ent.file_type = pick_integer_be(info_ptr, 0, 4);
- ent.file_creator = pick_integer_be(info_ptr, 4, 4);
- ent.finder_flags = pick_integer_be(info_ptr, 8, 2);
- ent.coord_x = pick_integer_be(info_ptr, 10, 2);
- ent.coord_y = pick_integer_be(info_ptr, 12, 2);
- ent.finder_folder = pick_integer_be(info_ptr, 14, 4);
- break;
-
- case 2: /* xFInfo */
- ent.icon_id = pick_integer_be(info_ptr, 0, 2);
- ent.script_code = pick_integer_be(info_ptr, 8, 1);
- ent.extended_flags = pick_integer_be(info_ptr, 9, 1);
- ent.comment_id = pick_integer_be(info_ptr, 10, 2);
- ent.putaway_directory = pick_integer_be(info_ptr, 12, 4);
- break;
- }
- }
- }
- }
- else
- {
- /* normal ProDOS files have all of the info right here */
- ent.key_pointer[0] = pick_integer_le(appleenum->block_data, offset + 17, 2);
- ent.filesize[0] = pick_integer_le(appleenum->block_data, offset + 21, 3);
- ent.depth[0] = ent.storage_type >> 4;
- }
-
- /* identify next entry */
- next_block = appleenum->block;
- next_index = appleenum->index + 1;
- if (next_index >= di->dirents_per_block)
- {
- next_block = pick_integer_le(appleenum->block_data, 2, 2);
- next_index = 0;
- }
-
- /* seek next block */
- err = prodos_enum_seek(image, appleenum, next_block, next_index);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/* changes a normal file to a ProDOS extended file */
-static imgtoolerr_t prodos_promote_file(imgtool::image &image, uint8_t *bitmap, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- uint16_t new_block;
- uint8_t buffer[BLOCK_SIZE];
-
- assert(is_normalfile_storagetype(ent->storage_type));
-
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create raw extended info block */
- memset(buffer, 0, sizeof(buffer));
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- ent->storage_type = (ent->storage_type & 0x0F) | 0x50;
- ent->extkey_pointer = new_block;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_put_dirent(imgtool::image &image,
- prodos_direnum *appleenum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint32_t offset;
- size_t finfo_offset;
- uint8_t buffer[BLOCK_SIZE];
- int fork_num;
- int needs_finfo = false;
- int needs_xfinfo = false;
- uint8_t *info_ptr;
- uint8_t *finfo;
- uint8_t *xfinfo;
-
- di = get_prodos_info(image);
- offset = appleenum->index * di->dirent_size + 4;
-
- /* determine whether we need FInfo and/or xFInfo */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- needs_finfo = (ent->file_type != 0x3F3F3F3F) ||
- (ent->file_creator != 0x3F3F3F3F) ||
- (ent->finder_flags != 0) ||
- (ent->coord_x != 0) ||
- (ent->coord_y != 0) ||
- (ent->finder_folder != 0);
-
- needs_xfinfo = (ent->icon_id != 0) ||
- (ent->script_code != 0) ||
- (ent->extended_flags != 0) ||
- (ent->comment_id != 0) ||
- (ent->putaway_directory != 0);
- }
-
- /* do we need to promote this file to an extended file? */
- if (!is_extendedfile_storagetype(ent->storage_type)
- && (needs_finfo || needs_xfinfo))
- {
- err = prodos_promote_file(image, NULL, ent);
- if (err)
- return err;
- }
-
- /* write out the storage type, filename, creation and lastmodified times */
- appleenum->block_data[offset + 0] = ent->storage_type;
- memcpy(&appleenum->block_data[offset + 1], ent->filename, 15);
- place_integer_le(appleenum->block_data, offset + 24, 4, ent->creation_time);
- place_integer_le(appleenum->block_data, offset + 33, 4, ent->lastmodified_time);
-
- if (is_extendedfile_storagetype(ent->storage_type))
- {
- /* ProDOS extended file */
- err = prodos_load_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- finfo = NULL;
- xfinfo = NULL;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- place_integer_le(buffer, 1 + (fork_num * 256), 2, ent->key_pointer[fork_num]);
- place_integer_le(buffer, 5 + (fork_num * 256), 3, ent->filesize[fork_num]);
- buffer[fork_num * 256] = ent->depth[fork_num];
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- finfo = info_ptr;
- break;
-
- case 2: /* xFInfo */
- xfinfo = info_ptr;
- break;
- }
- }
- }
-
- /* allocate the finfo and/or xinfo blocks, if we need them */
- if (needs_finfo && !finfo)
- finfo = alloc_info_block(buffer, 18, 1);
- if (needs_xfinfo && !xfinfo)
- xfinfo = alloc_info_block(buffer, 18, 2);
-
- if (finfo)
- {
- place_integer_be(finfo, 0, 4, ent->file_type);
- place_integer_be(finfo, 4, 4, ent->file_creator);
- place_integer_be(finfo, 8, 2, ent->finder_flags);
- place_integer_be(finfo, 10, 2, ent->coord_x);
- place_integer_be(finfo, 12, 2, ent->coord_y);
- place_integer_be(finfo, 14, 4, ent->finder_folder);
- }
-
- if (xfinfo)
- {
- place_integer_be(xfinfo, 0, 2, ent->icon_id);
- place_integer_be(xfinfo, 8, 1, ent->script_code);
- place_integer_be(xfinfo, 9, 1, ent->extended_flags);
- place_integer_be(xfinfo, 10, 2, ent->comment_id);
- place_integer_be(xfinfo, 12, 4, ent->putaway_directory);
- }
-
- err = prodos_save_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->extkey_pointer);
- place_integer_le(appleenum->block_data, offset + 21, 3, BLOCK_SIZE);
- }
- else
- {
- /* normal file */
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->key_pointer[0]);
- place_integer_le(appleenum->block_data, offset + 21, 3, ent->filesize[0]);
- }
-
- err = prodos_save_block(image, appleenum->block, appleenum->block_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_lookup_path(imgtool::image &image, const char *path,
- creation_policy_t create, prodos_direnum *direnum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_direnum my_direnum;
- uint32_t block = ROOTDIR_BLOCK;
- const char *old_path;
- uint16_t this_block;
- uint32_t this_index;
- uint16_t free_block = 0;
- uint32_t free_index = 0;
- uint16_t new_file_block;
- uint8_t buffer[BLOCK_SIZE];
-
- if (!direnum)
- direnum = &my_direnum;
-
- while(*path)
- {
- memset(direnum, 0, sizeof(*direnum));
- err = prodos_enum_seek(image, direnum, block, 0);
- if (err)
- goto done;
-
- do
- {
- this_block = direnum->block;
- this_index = direnum->index;
-
- err = prodos_get_next_dirent(image, direnum, *ent);
- if (err)
- goto done;
-
- /* if we need to create a file entry and this is free, track it */
- if (create && this_block && !free_block && !ent->storage_type)
- {
- free_block = this_block;
- free_index = this_index;
- }
- }
- while(direnum->block && (strcmp(path, ent->filename) || (
- !is_file_storagetype(ent->storage_type) &&
- !is_dir_storagetype(ent->storage_type))));
-
- old_path = path;
- path += strlen(path) + 1;
- if (*path)
- {
- /* we have found part of the path; we are not finished yet */
- if (!is_dir_storagetype(ent->storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
- block = ent->key_pointer[0];
- }
- else if (!direnum->block)
- {
- /* did not find file; maybe we need to create it */
- if (create == CREATE_NONE)
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- /* do we need to expand the directory? */
- if (!free_block)
- {
- if (this_block == 0)
- {
- err = IMGTOOLERR_CORRUPTFILE;
- goto done;
- }
-
- err = prodos_load_block(image, this_block, buffer);
- if (err)
- goto done;
-
- /* allocate a block */
- err = prodos_alloc_block(image, NULL, &free_block);
- if (err)
- goto done;
-
- /* clear out this new block */
- err = prodos_clear_block(image, free_block);
- if (err)
- goto done;
-
- /* save this link */
- place_integer_le(buffer, 2, 2, free_block);
- err = prodos_save_block(image, this_block, buffer);
- if (err)
- goto done;
-
- free_index = 0;
- }
-
- /* seek back to the free space */
- err = prodos_enum_seek(image, direnum, free_block, free_index);
- if (err)
- goto done;
-
- new_file_block = 0;
- if (create == CREATE_DIR)
- {
- /* if we are creating a directory, we need to create a new block */
- err = prodos_alloc_block(image, NULL, &new_file_block);
- if (err)
- goto done;
-
- err = prodos_clear_block(image, new_file_block);
- if (err)
- goto done;
- }
-
- /* prepare the dirent */
- memset(ent, 0, sizeof(*ent));
- ent->storage_type = (create == CREATE_DIR) ? 0xe0 : 0x10;
- ent->creation_time = ent->lastmodified_time = prodos_time_now();
- ent->key_pointer[0] = new_file_block;
- ent->file_type = 0x3F3F3F3F;
- ent->file_creator = 0x3F3F3F3F;
- strncpy(ent->filename, old_path, ARRAY_LENGTH(ent->filename));
-
- /* and place it */
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
-
- this_block = free_block;
- this_index = free_index;
- }
- else
- {
- /* we've found the file; seek that dirent */
- err = prodos_enum_seek(image, direnum, this_block, this_index);
- if (err)
- goto done;
- }
- }
-
- err = IMGTOOLERR_SUCCESS;
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_fill_file(imgtool::image &image, uint8_t *bitmap,
- uint16_t key_block, int key_block_allocated,
- int depth, uint32_t blockcount, uint32_t block_index)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int dirty;
- int sub_block_allocated;
- uint16_t i, sub_block, new_sub_block;
- uint8_t buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_block_allocated)
- {
- /* we are on a recently allocated key block; start fresh */
- memset(buffer, 0, sizeof(buffer));
- dirty = true;
- }
- else
- {
- /* this is a preexisting key block */
- err = prodos_load_block(image, key_block, buffer);
- if (err)
- return err;
- dirty = false;
- }
-
- for (i = 0; i < 256; i++)
- {
- sub_block_allocated = false;
-
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block += buffer[i + 0];
-
- new_sub_block = sub_block;
- if ((block_index < blockcount) && (sub_block == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_sub_block);
- if (err)
- return err;
- sub_block_allocated = true;
- }
- else if ((block_index >= blockcount) && (sub_block != 0))
- {
- new_sub_block = 0;
- if (sub_block < di->total_blocks)
- prodos_set_volume_bitmap_bit(bitmap, sub_block, 0);
- }
-
- /* did we change the block? */
- if (new_sub_block != sub_block)
- {
- dirty = true;
- buffer[i + 0] = new_sub_block >> 0;
- buffer[i + 256] = new_sub_block >> 8;
- if (sub_block == 0)
- sub_block = new_sub_block;
- }
-
- /* call recursive function */
- if (depth > 2)
- {
- err = prodos_fill_file(image, bitmap, sub_block, sub_block_allocated, depth - 1, blockcount, block_index);
- if (err)
- return err;
- }
-
- /* increment index */
- block_index += 1 << ((depth - 2) * 8);
- }
-
- /* if we changed anything, then save the block */
- if (dirty)
- {
- err = prodos_save_block(image, key_block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_block_count(imgtool::image &image, prodos_direnum *direnum,
- prodos_dirent *ent, uint8_t *bitmap, int fork_num, uint32_t new_blockcount)
-{
- imgtoolerr_t err;
- int depth, new_depth, i;
- uint16_t new_block, block;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t key_pointer;
-
- if (fork_num && (new_blockcount > 0) && !is_extendedfile_storagetype(ent->storage_type))
- {
- /* need to change a normal file to an extended file */
- err = prodos_promote_file(image, bitmap, ent);
- if (err)
- return err;
- }
-
- key_pointer = ent->key_pointer[fork_num];
- depth = ent->depth[fork_num];
-
- /* determine the new tree depth */
- if (new_blockcount <= 1)
- new_depth = 1;
- else if (new_blockcount <= 256)
- new_depth = 2;
- else
- new_depth = 3;
-
- /* are we zero length, and do we have to create a block? */
- if ((new_blockcount >= 1) && (key_pointer == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
- key_pointer = new_block;
- }
-
- /* do we have to grow the tree? */
- while(new_depth > depth)
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create this new key block, with a link to the previous one */
- memset(buffer, 0, sizeof(buffer));
- buffer[0] = (uint8_t) (key_pointer >> 0);
- buffer[256] = (uint8_t) (key_pointer >> 8);
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- depth++;
- key_pointer = new_block;
- }
-
- /* do we have to shrink the tree? */
- while(new_depth < depth)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 1; i < 256; i++)
- {
- block = buffer[i + 256];
- block <<= 8;
- block |= buffer[i + 0];
-
- if (block > 0)
- {
- if (depth > 2)
- {
- /* remove this block's children */
- err = prodos_fill_file(image, bitmap, block, false, depth - 1, 0, 0);
- if (err)
- return err;
- }
-
- /* and remove this block */
- prodos_set_volume_bitmap_bit(bitmap, block, 0);
- }
- }
-
- /* remove this key block */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
-
- /* set the new key pointer */
- block = buffer[256];
- block <<= 8;
- block |= buffer[0];
- key_pointer = block;
-
- depth--;
- }
-
- if (new_blockcount > 0)
- {
- /* fill out the file tree */
- err = prodos_fill_file(image, bitmap, key_pointer, false, depth, new_blockcount, 0);
- if (err)
- return err;
- }
- else if (key_pointer != 0)
- {
- /* we are now zero length, and don't need a key pointer */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
- key_pointer = 0;
- }
-
- /* change the depth if we are not an extended file */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- ent->storage_type &= ~0xF0;
- ent->storage_type |= depth * 0x10;
- }
-
- ent->key_pointer[fork_num] = key_pointer;
- ent->depth[fork_num] = depth;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_size(imgtool::image &image, prodos_direnum *direnum,
- prodos_dirent *ent, int fork_num, uint32_t new_size)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- uint32_t blockcount, new_blockcount;
- uint8_t *bitmap = NULL;
-
- if (ent->filesize[fork_num] != new_size)
- {
- blockcount = (ent->filesize[fork_num] + BLOCK_SIZE - 1) / BLOCK_SIZE;
- new_blockcount = (new_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-
- /* do we need to change the block chain? */
- if (new_blockcount != blockcount)
- {
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- err = prodos_set_file_block_count(image, direnum, ent, bitmap, fork_num, new_blockcount);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
-
- ent->filesize[fork_num] = new_size;
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static uint32_t prodos_get_storagetype_maxfilesize(uint8_t storage_type)
-{
- uint32_t max_filesize = 0;
- switch(storage_type & 0xF0)
- {
- case 0x10:
- max_filesize = BLOCK_SIZE * 1;
- break;
- case 0x20:
- max_filesize = BLOCK_SIZE * 256;
- break;
- case 0x30:
- case 0x50:
- max_filesize = BLOCK_SIZE * 32768;
- break;
- }
- return max_filesize;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_beginenum(imgtool::directory &enumeration, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(enumeration.image());
- prodos_direnum *appleenum;
- prodos_dirent ent;
- uint16_t block = ROOTDIR_BLOCK;
-
- appleenum = (prodos_direnum *) enumeration.extra_bytes();
-
- /* find subdirectory, if appropriate */
- if (*path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- block = ent.key_pointer[0];
- }
-
- /* seek initial block */
- err = prodos_enum_seek(image, appleenum, block, 0);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
-{
- imgtoolerr_t err;
- imgtool::image &image(enumeration.image());
- prodos_direnum *appleenum;
- prodos_dirent pd_ent;
- uint32_t max_filesize;
-
- appleenum = (prodos_direnum *) enumeration.extra_bytes();
-
- do
- {
- err = prodos_get_next_dirent(image, appleenum, pd_ent);
- if (err)
- return err;
- }
- while(appleenum->block
- && !is_file_storagetype(pd_ent.storage_type)
- && !is_dir_storagetype(pd_ent.storage_type));
-
- /* end of file? */
- if (pd_ent.storage_type == 0x00)
- {
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- strcpy(ent.filename, pd_ent.filename);
- ent.directory = is_dir_storagetype(pd_ent.storage_type);
- ent.creation_time = prodos_crack_time(pd_ent.creation_time);
- ent.lastmodified_time = prodos_crack_time(pd_ent.lastmodified_time);
-
- if (!ent.directory)
- {
- ent.filesize = pd_ent.filesize[0];
-
- max_filesize = prodos_get_storagetype_maxfilesize(pd_ent.storage_type);
- if (ent.filesize > max_filesize)
- {
- ent.corrupt = 1;
- ent.filesize = max_filesize;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_read_file_tree(imgtool::image &image, uint32_t *filesize,
- uint32_t block, int nest_level, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t sub_block;
- size_t bytes_to_write;
- int i;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- /* this is an index block */
- for (i = 0; i < 256; i++)
- {
- /* retrieve the block pointer; the two bytes are on either half
- * of the block */
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_read_file_tree(image, filesize, sub_block, nest_level - 1, destf);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_write = std::min(size_t(*filesize), sizeof(buffer));
- destf.write(buffer, bytes_to_write);
- *filesize -= bytes_to_write;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_write_file_tree(imgtool::image &image, uint32_t *filesize,
- uint32_t block, int nest_level, imgtool::stream &sourcef)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t sub_block;
- size_t bytes_to_read;
- int i;
-
- /* nothing more to read? bail */
- if (*filesize == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_write_file_tree(image, filesize, sub_block, nest_level - 1, sourcef);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_read = std::min(size_t(*filesize), sizeof(buffer));
- sourcef.read(buffer, bytes_to_read);
- *filesize -= bytes_to_read;
-
- err = prodos_save_block(image, block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_freespace(imgtool::partition &partition, uint64_t *size)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_diskinfo *di;
- uint8_t *bitmap = NULL;
- uint16_t i;
-
- di = get_prodos_info(image);
- *size = 0;
-
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- for (i = 0; i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- *size += BLOCK_SIZE;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- uint16_t key_pointer;
- int nest_level;
- mac_fork_t fork_num;
-
- err = prodos_lookup_path(image, filename, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- key_pointer = ent.key_pointer[fork_num];
- nest_level = ent.depth[fork_num] - 1;
-
- if (key_pointer != 0)
- {
- err = prodos_read_file_tree(image, &ent.filesize[fork_num], key_pointer,
- nest_level, destf);
- if (err)
- return err;
- }
-
- /* have we not actually received the correct amount of bytes? if not, fill in the rest */
- if (ent.filesize[fork_num] > 0)
- destf.fill(0, ent.filesize[fork_num]);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- uint64_t file_size;
- mac_fork_t fork_num;
-
- file_size = sourcef.size();
-
- err = prodos_lookup_path(image, filename, CREATE_FILE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* set the file size */
- err = prodos_set_file_size(image, &direnum, &ent, fork_num, file_size);
- if (err)
- return err;
-
- err = prodos_write_file_tree(image, &ent.filesize[fork_num], ent.key_pointer[fork_num],
- ent.depth[fork_num] - 1, sourcef);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletefile(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- /* empty out both forks */
- err = prodos_set_file_size(image, &direnum, &ent, 0, 0);
- if (err)
- return err;
- err = prodos_set_file_size(image, &direnum, &ent, 1, 0);
- if (err)
- return err;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_listforks(imgtool::partition &partition, const char *path, std::vector<imgtool::fork_entry> &forks)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- // specify data fork
- forks.emplace_back(ent.filesize[0], imgtool::fork_entry::type_t::DATA);
-
- if (is_extendedfile_storagetype(ent.storage_type))
- {
- // specify the resource fork
- forks.emplace_back(ent.filesize[1], imgtool::fork_entry::type_t::RESOURCE);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_createdir(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_DIR, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_free_directory(imgtool::image &image, uint8_t *volume_bitmap, uint16_t key_pointer)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- uint16_t next_block;
- uint32_t offset;
- uint8_t buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_pointer != 0)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 0; i < di->dirents_per_block; i++)
- {
- offset = i * di->dirent_size + 4;
-
- if (is_file_storagetype(buffer[offset]) || is_file_storagetype(buffer[offset]))
- return IMGTOOLERR_DIRNOTEMPTY;
- }
-
- next_block = pick_integer_le(buffer, 2, 2);
-
- err = prodos_free_directory(image, volume_bitmap, next_block);
- if (err)
- return err;
-
- prodos_set_volume_bitmap_bit(volume_bitmap, key_pointer, 0);
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletedir(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- uint8_t *volume_bitmap = NULL;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- goto done;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- err = prodos_load_volume_bitmap(image, &volume_bitmap);
- if (err)
- goto done;
-
- err = prodos_free_directory(image, volume_bitmap, ent.key_pointer[0]);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, volume_bitmap);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- goto done;
-
-done:
- if (volume_bitmap)
- free(volume_bitmap);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_get_file_tree(imgtool::image &image, imgtool_chainent *chain, size_t chain_size,
- size_t *chain_pos, uint16_t block, uint8_t total_depth, uint8_t cur_depth)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- uint16_t sub_block;
- uint8_t buffer[BLOCK_SIZE];
-
- if (block == 0)
- return IMGTOOLERR_SUCCESS;
- if (*chain_pos >= chain_size)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- chain[*chain_pos].level = cur_depth;
- chain[*chain_pos].block = block;
- (*chain_pos)++;
-
- /* must we recurse into the tree? */
- if (cur_depth < total_depth)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- err = prodos_get_file_tree(image, chain, chain_size, chain_pos, sub_block, total_depth, cur_depth + 1);
- if (err)
- return err;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = ent.file_type;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = ent.file_creator;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = ent.finder_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = ent.coord_x;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = ent.coord_y;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = ent.finder_folder;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = ent.icon_id;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = ent.script_code;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = ent.extended_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = ent.comment_id;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = ent.putaway_directory;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = prodos_crack_time(ent.creation_time).to_time_t();
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = prodos_crack_time(ent.lastmodified_time).to_time_t();
- break;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_setattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- ent.file_type = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- ent.file_creator = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- ent.finder_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- ent.coord_x = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- ent.coord_y = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- ent.finder_folder = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- ent.icon_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- ent.script_code = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- ent.extended_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- ent.comment_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- ent.putaway_directory = values[i].i;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- ent.creation_time = prodos_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- ent.lastmodified_time = prodos_setup_time(values[i].t);
- break;
- }
- }
-
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_suggesttransfer(imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- file_category = is_extendedfile_storagetype(ent.storage_type)
- ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getchain(imgtool::partition &partition, const char *path, imgtool_chainent *chain, size_t chain_size)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- size_t chain_pos = 0;
- int fork_num;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- switch(ent.storage_type & 0xF0)
- {
- case 0x10:
- case 0x20:
- case 0x30:
- /* normal ProDOS file */
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[0], ent.depth[0] - 1, 0);
- if (err)
- return err;
- break;
-
- case 0x50:
- /* extended ProDOS file */
- chain[chain_pos].level = 0;
- chain[chain_pos].block = ent.extkey_pointer;
- chain_pos++;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- if (ent.key_pointer[fork_num])
- {
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[fork_num], ent.depth[fork_num] - 1, 1);
- if (err)
- return err;
- }
- }
- break;
-
- case 0xE0:
- /* directory */
- return IMGTOOLERR_UNIMPLEMENTED;
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void generic_prodos_get_info(const imgtool_class *imgclass, uint32_t 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_SUPPORTS_CREATION_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_WRITING_UNTESTED: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(prodos_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(prodos_direnum); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "ProDOS 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_BEGIN_ENUM: info->begin_enum = prodos_diskimage_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = prodos_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = prodos_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = prodos_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = prodos_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = prodos_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = prodos_diskimage_listforks; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = prodos_diskimage_createdir; break;
- case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = prodos_diskimage_deletedir; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = prodos_diskimage_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = prodos_diskimage_setattrs; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = prodos_diskimage_suggesttransfer; break;
- case IMGTOOLINFO_PTR_GET_CHAIN: info->get_chain = prodos_diskimage_getchain; break;
- }
-}
-
-
-
-void prodos_525_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_525"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple2; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void prodos_35_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_35"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_iigs; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/tools/imgtool/modules/psion.cpp b/src/tools/imgtool/modules/psion.cpp
index 5759673349e..dba1130ddab 100644
--- a/src/tools/imgtool/modules/psion.cpp
+++ b/src/tools/imgtool/modules/psion.cpp
@@ -24,6 +24,11 @@
#include "imgtool.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+
#define MAXFILES 256
struct psion_file
@@ -54,24 +59,23 @@ static psion_pack *get_psion_pack(imgtool::image &image)
return (psion_pack*)image.extra_bytes();
}
-uint16_t head_checksum(uint8_t* data)
+uint16_t head_checksum(const uint8_t* data)
{
uint16_t checksum = 0;
for (int i=0; i<6; i+=2)
- checksum += (data[i]<<8 | data[i+1]);
+ checksum += get_u16be(&data[i]);
return checksum;
}
uint16_t get_long_rec_size(imgtool::stream &stream)
{
- uint8_t size_h, size_l;
+ uint8_t size[2];
- stream.read(&size_h, 1);
- stream.read(&size_l, 1);
+ stream.read(size, 2);
- return (size_h<<8) | size_l;
+ return get_u16be(size);
}
uint32_t update_pack_index(psion_pack *pack)
@@ -245,6 +249,7 @@ char *stream_getline(imgtool::stream &source, uint16_t max_len)
source.read(&data, 1);
if (data != '\n')
source.seek(-1, SEEK_CUR);
+ [[fallthrough]];
case '\n':
return line;
default:
@@ -483,7 +488,7 @@ static imgtoolerr_t datapack_next_enum(imgtool::directory &enumeration, imgtool_
return IMGTOOLERR_SUCCESS;
}
memcpy(ent.filename, pack->pack_index[iter->index].filename, 8);
- sprintf(ent.attr, "Type: %02x ID: %02x", pack->pack_index[iter->index].type, pack->pack_index[iter->index].id);
+ snprintf(ent.attr, std::size(ent.attr), "Type: %02x ID: %02x", pack->pack_index[iter->index].type, pack->pack_index[iter->index].id);
if (pack->pack_index[iter->index].data_rec)
{
diff --git a/src/tools/imgtool/modules/rsdos.cpp b/src/tools/imgtool/modules/rsdos.cpp
index 4bcde9444ab..b4924338309 100644
--- a/src/tools/imgtool/modules/rsdos.cpp
+++ b/src/tools/imgtool/modules/rsdos.cpp
@@ -8,13 +8,18 @@
****************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "imgtool.h"
-#include "formats/coco_dsk.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "formats/coco_dsk.h"
+#include "corestr.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/* this structure mirrors the structure of an RS-DOS directory entry on disk */
struct rsdos_dirent
{
@@ -103,7 +108,7 @@ static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, rsdo
if (ent.filename[0] != -1)
fnamebuf = get_dirent_fname(ent);
}
- while((ent.filename[0] != -1) && core_stricmp(fnamebuf.c_str(), fname));
+ while((ent.filename[0] != -1) && core_stricmp(fnamebuf, fname));
if (ent.filename[0] == -1)
return IMGTOOLERR_FILENOTFOUND;
@@ -320,7 +325,7 @@ eof:
}
else
{
- /* Not the end of file */
+ /* Note the end of file */
err = process_rsdos_file(&rsent, image, nullptr, filesize);
if (err)
return err;
@@ -340,8 +345,8 @@ eof:
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'));
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname.c_str());
+ snprintf(ent.attr, std::size(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
}
return IMGTOOLERR_SUCCESS;
}
@@ -568,7 +573,7 @@ static imgtoolerr_t rsdos_diskimage_deletefile(imgtool::partition &partition, co
// rsdos_diskimage_suggesttransfer
//-------------------------------------------------
-static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t err;
imgtool::image &image(partition.image());
@@ -584,27 +589,27 @@ static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partitio
if (ent.asciiflag == (char) 0xFF)
{
/* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
}
else if (ent.ftype == 0)
{
/* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_cocobas_getinfo;
}
}
else
{
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_cocobas_getinfo;
}
@@ -640,7 +645,7 @@ void rsdos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct rsdos_direnum); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "rsdos"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "RS-DOS format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
diff --git a/src/tools/imgtool/modules/rt11.cpp b/src/tools/imgtool/modules/rt11.cpp
index 01ab8741dd6..cc425adbdb6 100644
--- a/src/tools/imgtool/modules/rt11.cpp
+++ b/src/tools/imgtool/modules/rt11.cpp
@@ -72,12 +72,13 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
#include "iflopimg.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "multibyte.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
namespace
@@ -384,17 +385,17 @@ static imgtoolerr_t rt11_image_open(imgtool::image &image, imgtool::stream::ptr
if (err)
return err;
- di->directory_start = pick_integer_le(buffer, 0724, 2);
+ di->directory_start = get_u16le(&buffer[0724]);
// real-world images seem to never have a valid checksum, but directory_start is always 6
#if 0
uint16_t tmp, cksum;
tmp = 0;
- cksum = pick_integer_le(buffer, 0776, 2);
+ cksum = get_u16le(&buffer[0776]);
for (int i = 0; i < 510; i+=2)
{
- tmp += pick_integer_le(buffer, i, 2);
+ tmp += get_u16le(&buffer[i]);
}
/* sanity check these values */
@@ -414,9 +415,9 @@ static imgtoolerr_t rt11_image_open(imgtool::image &image, imgtool::stream::ptr
if (err)
return err;
- di->total_segments = pick_integer_le(buffer, 0, 2);
- di->last_segment = pick_integer_le(buffer, 4, 2);
- di->dirent_size = (pick_integer_le(buffer, 6, 2) + 7) * 2;
+ di->total_segments = get_u16le(&buffer[0]);
+ di->last_segment = get_u16le(&buffer[4]);
+ di->dirent_size = (get_u16le(&buffer[6]) + 7) * 2;
di->dirents_per_block = (2 * BLOCK_SIZE - 10) / di->dirent_size;
return IMGTOOLERR_SUCCESS;
@@ -465,7 +466,7 @@ static imgtoolerr_t rt11_enum_seek(imgtool::image &image,
return err;
memcpy(&rt11enum->segment_data[BLOCK_SIZE], buffer, sizeof(buffer));
- rt11enum->data = pick_integer_le(rt11enum->segment_data, 8, 2);
+ rt11enum->data = get_u16le(&rt11enum->segment_data[8]);
}
rt11enum->segment = segment;
}
@@ -490,19 +491,19 @@ static imgtoolerr_t rt11_get_next_dirent(imgtool::image &image,
/* populate the resulting dirent */
offset = (rt11enum->index * di->dirent_size) + 10;
- rt_ent.status = pick_integer_le(rt11enum->segment_data, offset, 2);
+ rt_ent.status = get_u16le(&rt11enum->segment_data[offset]);
memcpy(rt_ent.filename, &rt11enum->segment_data[offset + 2], 6);
- rt_ent.filesize = pick_integer_le(rt11enum->segment_data, offset + 8, 2) * BLOCK_SIZE;
+ rt_ent.filesize = get_u16le(&rt11enum->segment_data[offset + 8]) * BLOCK_SIZE;
rt_ent.data = rt11enum->data;
- rt_ent.time = pick_integer_le(rt11enum->segment_data, offset + 12, 2);
- rt11enum->data += pick_integer_le(rt11enum->segment_data, offset + 8, 2);
+ rt_ent.time = get_u16le(&rt11enum->segment_data[offset + 12]);
+ rt11enum->data += get_u16le(&rt11enum->segment_data[offset + 8]);
/* identify next entry */
next_segment = rt11enum->segment;
next_index = rt11enum->index + 1;
if (next_index >= di->dirents_per_block || (rt_ent.status & E_EOS))
{
- next_segment = pick_integer_le(rt11enum->segment_data, 2, 2);
+ next_segment = get_u16le(&rt11enum->segment_data[2]);
next_index = 0;
}
diff --git a/src/tools/imgtool/modules/thomson.cpp b/src/tools/imgtool/modules/thomson.cpp
index f122bc00520..1978e3720ba 100644
--- a/src/tools/imgtool/modules/thomson.cpp
+++ b/src/tools/imgtool/modules/thomson.cpp
@@ -112,10 +112,15 @@
*/
#include "imgtool.h"
+#include "filter.h"
#include "iflopimg.h"
-#include "formats/imageutl.h"
-#include <time.h>
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <ctime>
#define MAXSIZE 80*16*256*2 /* room for two faces, double-density, 80 tracks */
@@ -590,14 +595,14 @@ static int thom_find_dirent(thom_floppy* f, unsigned head,
{
int n = 0;
while ( 1 ) {
- thom_get_dirent( f, head, n, d );
- if ( d->type == THOM_DIRENT_END ) return 0;
- if ( d->type == THOM_DIRENT_FILE ) {
- char buf[13];
- sprintf( buf, "%s.%s", d->name, d->ext );
- if ( ! strcmp( buf, name ) ) return 1;
- }
- n++;
+ thom_get_dirent( f, head, n, d );
+ if ( d->type == THOM_DIRENT_END ) return 0;
+ if ( d->type == THOM_DIRENT_FILE ) {
+ char buf[13];
+ snprintf( buf, std::size(buf), "%s.%s", d->name, d->ext );
+ if ( ! strcmp( buf, name ) ) return 1;
+ }
+ n++;
}
}
@@ -952,7 +957,7 @@ static imgtoolerr_t thom_read_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
if ( ! thom_find_dirent( f, head, fname, &d ) )
return IMGTOOLERR_FILENOTFOUND;
@@ -973,7 +978,7 @@ static imgtoolerr_t thom_delete_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
if ( ! thom_find_dirent( f, head, fname, &d ) )
return IMGTOOLERR_FILENOTFOUND;
@@ -1002,7 +1007,7 @@ static imgtoolerr_t thom_write_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
/* check available space & find dir entry */
if ( thom_find_dirent( f, head, fname, &d ) ) {
@@ -1067,10 +1072,11 @@ static imgtoolerr_t thom_write_file(imgtool::partition &part,
return IMGTOOLERR_SUCCESS;
}
-static imgtoolerr_t thom_suggest_transfer(imgtool::partition &part,
- const char *fname,
- imgtool_transfer_suggestion *suggestions,
- size_t suggestions_length)
+static imgtoolerr_t thom_suggest_transfer(
+ imgtool::partition &part,
+ const char *fname,
+ imgtool::transfer_suggestion *suggestions,
+ size_t suggestions_length)
{
int head = *( (int*) part.extra_bytes() );
imgtool::image &img(part.image());
@@ -1081,30 +1087,30 @@ static imgtoolerr_t thom_suggest_transfer(imgtool::partition &part,
if ( suggestions_length < 1 ) return IMGTOOLERR_SUCCESS;
if ( fname ) {
- if ( ! thom_find_dirent( f, head, fname, &d ) )
- return IMGTOOLERR_FILENOTFOUND;
- if ( d.ftype == 0 && d.format == 0 ) is_basic = 1;
+ if ( ! thom_find_dirent( f, head, fname, &d ) )
+ return IMGTOOLERR_FILENOTFOUND;
+ if ( d.ftype == 0 && d.format == 0 ) is_basic = 1;
}
if ( is_basic ) {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_thombas128_getinfo;
- if ( suggestions_length >= 2 ) {
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_thombas7_getinfo;
- }
- if ( suggestions_length >= 3 ) {
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_thombas5_getinfo;
- }
- if ( suggestions_length >= 4 ) {
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- }
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = filter_thombas128_getinfo;
+ if ( suggestions_length >= 2 ) {
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = filter_thombas7_getinfo;
+ }
+ if ( suggestions_length >= 3 ) {
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[2].filter = filter_thombas5_getinfo;
+ }
+ if ( suggestions_length >= 4 ) {
+ suggestions[3].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[3].filter = nullptr;
+ }
}
else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
}
return IMGTOOLERR_SUCCESS;
@@ -1206,12 +1212,12 @@ static const char *const thombas7[2][128] = {
/* MO5: some keywords ar missing; DOS and TUNE are added */
static const char *const thombas5[2][128] = {
{ /* statements */
- "END", "FOR", "NEXT", "DATA", "DIM", "READ", NULL, "GO", "RUN", "IF",
+ "END", "FOR", "NEXT", "DATA", "DIM", "READ", nullptr, "GO", "RUN", "IF",
"RESTORE", "RETURN", "REM", "'", "STOP", "ELSE", "TRON", "TROFF", "DEFSTR",
- "DEFINT", "DEFSNG", NULL, "ON", "TUNE", "ERROR", "RESUME", "AUTO",
+ "DEFINT", "DEFSNG", nullptr, "ON", "TUNE", "ERROR", "RESUME", "AUTO",
"DELETE", "LOCATE", "CLS", "CONSOLE", "PSET", "MOTOR", "SKIP", "EXEC",
- "BEEP", "COLOR", "LINE", "BOX", NULL, "ATTRB", "DEF", "POKE", "PRINT",
- "CONT", "LIST", "CLEAR", "DOS", NULL, "NEW", "SAVE", "LOAD", "MERGE",
+ "BEEP", "COLOR", "LINE", "BOX", nullptr, "ATTRB", "DEF", "POKE", "PRINT",
+ "CONT", "LIST", "CLEAR", "DOS", nullptr, "NEW", "SAVE", "LOAD", "MERGE",
"OPEN", "CLOSE", "INPEN", "PEN", "PLAY", "TAB(", "TO", "SUB", "FN",
"SPC(", "USING", "USR", "ERL", "ERR", "OFF", "THEN", "NOT", "STEP",
"+", "-", "*", "/", "^", "AND", "OR", "XOR", "EQV", "IMP", "MOD", "@",
@@ -1224,8 +1230,8 @@ static const char *const thombas5[2][128] = {
},
{ /* functions: 0xff prefix */
"SGN", "INT", "ABS", "FRE", "SQR", "LOG", "EXP", "COS", "SIN",
- "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", NULL,
- NULL, "FIX", "HEX$", NULL, "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
+ "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", nullptr,
+ nullptr, "FIX", "HEX$", nullptr, "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
"MID$", "INSTR", "VARPTR", "RND", "INKEY$", "INPUT", "CSRLIN", "POINT",
"SCREEN", "POS", "PTRIG",
/* DOS specific */
@@ -1368,7 +1374,7 @@ static imgtoolerr_t thomcrypt_write_file(imgtool::partition &part,
}
}
-void filter_thomcrypt_getinfo(uint32_t state, union filterinfo *info)
+void filter_thomcrypt_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state) {
case FILTINFO_STR_NAME:
@@ -1596,16 +1602,14 @@ struct {
{ "\xc3\xa7", "\x16" "Kc" },
{ "\xc3\x87", "\x16" "KC" },
- { NULL, NULL }
+ { nullptr, nullptr }
};
static bool thom_basic_is_specialchar(const char *buf,
int *pos,
const char **thom)
{
- int i;
-
- for (i = 0; special_chars[i].utf8 != NULL; i++)
+ for (int i = 0; special_chars[i].utf8 != nullptr; i++)
{
if (!strncmp(&buf[*pos], special_chars[i].utf8, strlen(special_chars[i].utf8)))
{
@@ -1740,7 +1744,7 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
if ((c == '\r') || (c == '\n'))
break;
- if (pos <= ARRAY_LENGTH(buf) - 1)
+ if (pos <= std::size(buf) - 1)
{
buf[pos++] = c;
}
@@ -1765,8 +1769,8 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
/* set up line header */
memset(&line_header, 0, sizeof(line_header));
/* linelength or offset (2-bytes) will be rewritten */
- place_integer_be(line_header, 0, 2, 0xffff);
- place_integer_be(line_header, 2, 2, line_number);
+ put_u16be(&line_header[0], 0xffff);
+ put_u16be(&line_header[2], line_number);
/* emit line header */
line_header_loc = mem_stream->tell();
@@ -1841,7 +1845,7 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
/* rewrite the line length */
end_line_loc = mem_stream->tell();
mem_stream->seek(line_header_loc, SEEK_SET);
- place_integer_be(line_header, 0, 2, end_line_loc - line_header_loc);
+ put_u16be(&line_header[0], end_line_loc - line_header_loc);
mem_stream->write(line_header, sizeof(line_header));
mem_stream->seek(end_line_loc, SEEK_SET);
}
@@ -1854,8 +1858,8 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
mem_stream->seek(0, SEEK_SET);
/* Write file header */
- place_integer_be(file_header, 0, 1, 0xFF);
- place_integer_be(file_header, 1, 2, mem_stream->size());
+ file_header[0] = 0xFF;
+ put_u16be(&file_header[1], mem_stream->size());
mem_stream->write(file_header, 3);
mem_stream->seek(0, SEEK_SET);
@@ -1870,32 +1874,33 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
const char *fork, \
imgtool::stream &dst) \
{ \
- return thom_basic_read_file( part, name, fork, dst, short ); \
+ return thom_basic_read_file( part, name, fork, dst, short ); \
} \
- static imgtoolerr_t short##_write_file(imgtool::partition &part, \
- const char *name, \
- const char *fork, \
- imgtool::stream &src, \
- util::option_resolution *opts) \
+ static imgtoolerr_t short##_write_file( \
+ imgtool::partition &part, \
+ const char *name, \
+ const char *fork, \
+ imgtool::stream &src, \
+ util::option_resolution *opts) \
{ \
- return thom_basic_write_file( part, name, fork, src, opts, short ); \
+ return thom_basic_write_file( part, name, fork, src, opts, short ); \
} \
- void filter_##short##_getinfo(uint32_t state, union filterinfo *info) \
+ void filter_##short##_getinfo(uint32_t state, imgtool::filterinfo *info) \
{ \
switch(state) \
{ \
case FILTINFO_STR_NAME: \
- info->s = #short; \
- break; \
+ info->s = #short; \
+ break; \
case FILTINFO_STR_HUMANNAME: \
- info->s = long; \
- break; \
+ info->s = long; \
+ break; \
case FILTINFO_PTR_READFILE: \
- info->read_file = short##_read_file; \
- break; \
+ info->read_file = short##_read_file; \
+ break; \
case FILTINFO_PTR_WRITEFILE: \
- info->write_file = short##_write_file; \
- break; \
+ info->write_file = short##_write_file; \
+ break; \
} \
}
@@ -1941,57 +1946,57 @@ static void thom_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES:
- info->i = sizeof(thom_floppy); break;
+ info->i = sizeof(thom_floppy); break;
case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES:
- info->i = sizeof(int); break;
+ info->i = sizeof(int); break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES:
- info->i = sizeof(int); break;
+ info->i = sizeof(int); break;
case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME:
case IMGTOOLINFO_INT_PREFER_UCASE:
- info->i = 1; break;
+ info->i = 1; break;
case IMGTOOLINFO_INT_PATH_SEPARATOR:
- info->i = 0; break;
+ info->i = 0; break;
case IMGTOOLINFO_STR_FILE:
- strcpy( info->s = imgtool_temp_str(), __FILE__ ); break;
+ strcpy( info->s = imgtool_temp_str(), __FILE__ ); break;
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(), "Thomson BASIC filesystem" );
- break;
+ strcpy( info->s = imgtool_temp_str(), "Thomson BASIC filesystem" );
+ break;
case IMGTOOLINFO_PTR_CREATE:
- info->create = thom_create; break;
+ info->create = thom_create; break;
case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE:
- info->createimage_optguide = &thom_createimage_optguide; break;
+ info->createimage_optguide = &thom_createimage_optguide; break;
case IMGTOOLINFO_PTR_BEGIN_ENUM:
- info->begin_enum = thom_begin_enum; break;
+ info->begin_enum = thom_begin_enum; break;
case IMGTOOLINFO_PTR_NEXT_ENUM:
- info->next_enum = thom_next_enum; break;
+ info->next_enum = thom_next_enum; break;
case IMGTOOLINFO_PTR_READ_FILE:
- info->read_file = thom_read_file; break;
+ info->read_file = thom_read_file; break;
case IMGTOOLINFO_PTR_WRITE_FILE:
- info->write_file = thom_write_file; break;
+ info->write_file = thom_write_file; break;
case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE:
- info->writefile_optguide = &thom_writefile_optguide; break;
+ info->writefile_optguide = &thom_writefile_optguide; break;
case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break;
+ strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break;
case IMGTOOLINFO_PTR_SUGGEST_TRANSFER:
- info->suggest_transfer = thom_suggest_transfer; break;
+ info->suggest_transfer = thom_suggest_transfer; break;
case IMGTOOLINFO_PTR_DELETE_FILE:
- info->delete_file = thom_delete_file; break;
+ info->delete_file = thom_delete_file; break;
case IMGTOOLINFO_PTR_FREE_SPACE:
- info->free_space = thom_free_space; break;
+ info->free_space = thom_free_space; break;
case IMGTOOLINFO_PTR_GET_GEOMETRY:
- info->get_geometry = thom_get_geometry; break;
+ info->get_geometry = thom_get_geometry; break;
case IMGTOOLINFO_PTR_INFO:
- info->info = thom_info; break;
+ info->info = thom_info; break;
case IMGTOOLINFO_PTR_READ_SECTOR:
- info->read_sector = thom_read_sector; break;
+ info->read_sector = thom_read_sector; break;
case IMGTOOLINFO_PTR_WRITE_SECTOR:
- info->write_sector = thom_write_sector; break;
+ info->write_sector = thom_write_sector; break;
case IMGTOOLINFO_PTR_LIST_PARTITIONS:
- info->list_partitions = thom_list_partitions; break;
+ info->list_partitions = thom_list_partitions; break;
case IMGTOOLINFO_PTR_OPEN_PARTITION:
- info->open_partition = thom_open_partition; break;
+ info->open_partition = thom_open_partition; break;
}
}
@@ -2001,21 +2006,21 @@ void thom_fd_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_fd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_fd" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .fd disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .fd disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "fd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "fd" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
+ info->open = thom_open_fd_qd; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
+ info->close = thom_close_fd_qd; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T40/[80];D0-[1];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1]-2;T40/[80];D0-[1];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
@@ -2025,21 +2030,21 @@ void thom_qd_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_qd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_qd" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .qd disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .qd disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "qd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "qd" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
+ info->open = thom_open_fd_qd; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
+ info->close = thom_close_fd_qd; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T[25];D[0];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1]-2;T[25];D[0];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
@@ -2049,20 +2054,20 @@ void thom_sap_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_sap" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_sap" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .sap disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .sap disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "sap" ); break;
+ strcpy( info->s = imgtool_temp_str(), "sap" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_sap; break;
+ info->open = thom_open_sap; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_sap; break;
+ info->close = thom_close_sap; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1];T40/[80];D0-[1];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1];T40/[80];D0-[1];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
diff --git a/src/tools/imgtool/modules/ti99.cpp b/src/tools/imgtool/modules/ti99.cpp
index 04881c7b5ef..3f57f91db7c 100644
--- a/src/tools/imgtool/modules/ti99.cpp
+++ b/src/tools/imgtool/modules/ti99.cpp
@@ -18,15 +18,18 @@
- check allocation bitmap against corruption when an image is opened
*/
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
#include "imgtool.h"
#include "harddisk.h"
#include "imghd.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
/*
Concepts shared by both disk structures:
----------------------------------------
@@ -166,7 +169,7 @@
The DSK disk structure is used for floppy disks, and a few RAMDISKs as
well. It supports 1600 AUs and 16 MBytes at most (the 16 MByte value is a
- theorical maximum, as I doubt anyone has ever created so big a DSK volume).
+ theoretical maximum, as I doubt anyone has ever created so big a DSK volume).
The disk sector size is always 256 bytes (the only potential exceptions are
the SCSI floppy disk units and the TI-99 simulator on TI-990, but I don't
@@ -524,7 +527,7 @@ struct dsk_vib
/* the allocation unit associated with that */
/* bit has been allocated. */
/* Bits corresponding to system reserved AUs, */
- /* non-existant AUs, and bad AUs, are set to one, too. */
+ /* non-existent AUs, and bad AUs, are set to one, too. */
/* (AU 0 is associated to LSBit of byte 0, */
/* AU 7 to MSBit of byte 0, AU 8 to LSBit */
/* of byte 1, etc.) */
@@ -976,17 +979,15 @@ static imgtoolerr_t open_image_lvl1(imgtool::stream::ptr &&file_handle, ti99_img
if (img_format == if_harddisk)
{
- const hard_disk_info *info;
-
err = imghd_open(*file_handle, &l1_img->harddisk_handle);
if (err)
return err;
- info = imghd_get_header(&l1_img->harddisk_handle);
- l1_img->geometry.cylinders = info->cylinders;
- l1_img->geometry.heads = info->heads;
- l1_img->geometry.secspertrack = info->sectors;
- if (info->sectorbytes != 256)
+ const auto &info = imghd_get_header(&l1_img->harddisk_handle);
+ l1_img->geometry.cylinders = info.cylinders;
+ l1_img->geometry.heads = info.heads;
+ l1_img->geometry.secspertrack = info.sectors;
+ if (info.sectorbytes != 256)
{
imghd_close(&l1_img->harddisk_handle);
return IMGTOOLERR_CORRUPTIMAGE; /* TODO: support 512-byte sectors */
@@ -1300,15 +1301,13 @@ static void dsk_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *ge
geometry (I): disk image geometry
address (O): physical sector address
*/
-#ifdef UNUSED_FUNCTION
-static void win_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *geometry, ti99_sector_address *address)
+[[maybe_unused]] static void win_aphysrec_to_sector_address(int aphysrec, const ti99_geometry &geometry, ti99_sector_address &address)
{
- address.sector = aphysrec % l1_img->geometry.secspertrack;
- aphysrec /= l1_img->geometry.secspertrack;
- address.side = aphysrec % l1_img->geometry.heads;
- address.cylinder = aphysrec / l1_img->geometry.heads;
+ address.sector = aphysrec % geometry.secspertrack;
+ aphysrec /= geometry.secspertrack;
+ address.side = aphysrec % geometry.heads;
+ address.cylinder = aphysrec / geometry.heads;
}
-#endif
/*
Read one 256-byte physical record from a disk image
@@ -1327,7 +1326,7 @@ static int read_absolute_physrec(ti99_lvl1_imgref *l1_img, unsigned aphysrec, vo
if (l1_img->img_format == if_harddisk)
{
#if 0
- win_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
+ win_aphysrec_to_sector_address(aphysrec, l1_img->geometry, address);
return read_sector(l1_img, & address, dest);
#endif
@@ -1563,7 +1562,7 @@ struct dsk_fdr
UINT16BE xreclen; /* extended record len: if record len is >= 256, */
/* reclen is set to 0 and the actual reclen is */
/* stored here (Myarc HFDC only). TI reserved */
- /* this field for data chain pointer extension, */
+ /* this field for data chain pointer extension, */
/* but this was never implemented. */
uint8_t flags; /* file status flags (see enum above) */
uint8_t recsperphysrec; /* logical records per physrec */
@@ -1579,9 +1578,9 @@ struct dsk_fdr
/* implementation is regarded as a bug because */
/* program files do not define the fixrecs field */
/* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
+ /* DSR may be larger than they should. */
uint8_t eof; /* EOF offset in last physrec for variable length */
- /* record files and program files (0->256)*/
+ /* record files and program files (0->256) */
uint8_t reclen; /* logical record size in bytes ([1,255] 0->256) */
/* Maximum allowable record size for variable */
/* length record files. Reserved for program */
@@ -1625,7 +1624,7 @@ struct win_fdr
/* implementation is regarded as a bug because */
/* program files do not define the fixrecs field */
/* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
+ /* DSR may be larger than they should. */
/* other sibling FDRs: index of the first file */
/* physrec in this particular sibling FDR */
uint8_t eof; /* EOF offset in last physrec for variable length */
@@ -1837,7 +1836,7 @@ static int dsk_read_catalog(struct ti99_lvl2_imgref *l2_img, int aphysrec, ti99_
|| ((dest->files[i].fdr_ptr && dest->files[i+1].fdr_ptr) && (memcmp(dest->files[i].name, dest->files[i+1].name, 10) >= 0)))
{
/* if the catalog is not sorted, we repair it */
- qsort(dest->files, ARRAY_LENGTH(dest->files), sizeof(dest->files[0]),
+ qsort(dest->files, std::size(dest->files), sizeof(dest->files[0]),
cat_file_compare_qsort);
break;
}
@@ -3304,8 +3303,7 @@ static int write_file_physrec(struct ti99_lvl2_fileref *l2_file, unsigned fphysr
/*
Write a field in every fdr record associated to a file
*/
-#ifdef UNUSED_FUNCTION
-static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, size_t size, void *data)
+[[maybe_unused]] static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, size_t size, void *data)
{
win_fdr fdr_buf;
unsigned fdr_aphysrec;
@@ -3313,7 +3311,7 @@ static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, s
for (fdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
fdr_aphysrec && ((errorcode = (read_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf) ? IMGTOOLERR_READERROR : 0)) == 0);
- fdr_aphysrec = get_win_fdr_nextsibFDR_physrec(l2_file->win.l2_img, &fdr_buf))
+ fdr_aphysrec = get_win_fdr_nextsibFDR_aphysrec(l2_file->win.l2_img, &fdr_buf))
{
memcpy(((uint8_t *) &fdr_buf) + offset, data, size);
if (write_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf))
@@ -3325,7 +3323,6 @@ static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, s
return errorcode;
}
-#endif
static uint8_t get_file_flags(struct ti99_lvl2_fileref *l2_file)
{
@@ -3675,11 +3672,10 @@ static void set_file_update_date(struct ti99_lvl2_fileref *l2_file, ti99_date_ti
}
}
-#ifdef UNUSED_FUNCTION
-static void current_date_time(ti99_date_time *reply)
+[[maybe_unused]] static void current_date_time(ti99_date_time *reply)
{
/* All these functions should be ANSI */
- time_t cur_time = time(NULL);
+ time_t cur_time = time(nullptr);
struct tm expanded_time = *localtime(& cur_time);
reply->time_MSB = (expanded_time.tm_hour << 3) | (expanded_time.tm_min >> 3);
@@ -3687,7 +3683,6 @@ static void current_date_time(ti99_date_time *reply)
reply->date_MSB = ((expanded_time.tm_year % 100) << 1) | ((expanded_time.tm_mon+1) >> 3);
reply->date_LSB = ((expanded_time.tm_mon+1) << 5) | expanded_time.tm_mday;
}
-#endif
#if 0
#pragma mark -
@@ -3712,14 +3707,13 @@ struct ti99_lvl3_fileref
int cur_pos_in_phys_rec;
};
-#ifdef UNUSED_FUNCTION
/*
Open a file on level 3.
To open a file on level 3, you must open (or create) the file on level 2,
then pass the file reference to open_file_lvl3.
*/
-static int open_file_lvl3(ti99_lvl3_fileref *l3_file)
+[[maybe_unused]] static int open_file_lvl3(ti99_lvl3_fileref *l3_file)
{
l3_file->cur_log_rec = 0;
l3_file->cur_phys_rec = 0;
@@ -3754,7 +3748,7 @@ static int is_eof(ti99_lvl3_fileref *l3_file)
/*
Read next record from a file
*/
-static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_reclen)
+[[maybe_unused]] static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_reclen)
{
int errorcode;
uint8_t physrec_buf[256];
@@ -3824,7 +3818,6 @@ static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_rec
return 0;
}
-#endif
#if 0
#pragma mark -
@@ -4275,10 +4268,10 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
{
if (iter->listing_subdirs)
{
- fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[iter->level]].name, std::size(ent.filename));
/* set type of DIR */
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "DIR");
+ snprintf(ent.attr, std::size(ent.attr), "DIR");
/* len in physrecs */
/* @BN@ return length in bytes */
@@ -4299,7 +4292,7 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
if (reply)
return IMGTOOLERR_READERROR;
#if 0
- fname_to_str(ent.filename, fdr.name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, fdr.name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4307,19 +4300,19 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
ent.filename[0] = '\0';
if (iter->level)
{
- fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[0]].name, ARRAY_LENGTH(ent.filename));
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[0]].name, std::size(ent.filename));
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, fdr.name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* parse flags */
if (fdr.flags & fdr99_f_program)
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "PGM%s",
+ snprintf(ent.attr, std::size(ent.attr), "PGM%s",
(fdr.flags & fdr99_f_wp) ? " R/O" : "");
else
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%c/%c %d%s",
+ snprintf(ent.attr, std::size(ent.attr), "%c/%c %d%s",
(fdr.flags & fdr99_f_int) ? 'I' : 'D',
(fdr.flags & fdr99_f_var) ? 'V' : 'F',
fdr.reclen,
@@ -4399,7 +4392,7 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
if (iter->listing_subdirs)
{
#if 0
- fname_to_str(ent.filename, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4408,16 +4401,16 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* set type of DIR */
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "DIR");
+ snprintf(ent.attr, std::size(ent.attr), "DIR");
/* len in physrecs */
/* @BN@ return length in bytes */
@@ -4442,7 +4435,7 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
if (reply)
return IMGTOOLERR_READERROR;
#if 0
- fname_to_str(ent.filename, iter->catalog[iter->level].files[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->catalog[iter->level].files[iter->index[iter->level]].name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4451,19 +4444,19 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->catalog[iter->level].files[iter->index[iter->level]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* parse flags */
if (fdr.flags & fdr99_f_program)
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "PGM%s",
+ snprintf(ent.attr, std::size(ent.attr), "PGM%s",
(fdr.flags & fdr99_f_wp) ? " R/O" : "");
else
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%c/%c %d%s",
+ snprintf(ent.attr, std::size(ent.attr), "%c/%c %d%s",
(fdr.flags & fdr99_f_int) ? 'I' : 'D',
(fdr.flags & fdr99_f_var) ? 'V' : 'F',
fdr.reclen,
@@ -4948,7 +4941,7 @@ static imgtoolerr_t dsk_image_deletefile(imgtool::partition &partition, const ch
/* free data AUs */
// fphysrecs =
- get_UINT16BE(fdr.fphysrecs);
+ get_UINT16BE(fdr.fphysrecs);
i = 0;
cluster_index = 0;
@@ -5090,7 +5083,7 @@ static imgtoolerr_t win_image_deletefile(imgtool::partition &partition, const ch
/* check integrity of FDR sibling chain, and go to last sibling */
/* note that as we check that the back chain is consistent with the forward
chain, we will also detect any cycle in the sibling chain, so we do not
- need to check against them explicitely */
+ need to check against them explicitly */
{
int pastendoflist_flag;
unsigned prevfdr_aphysrec;
diff --git a/src/tools/imgtool/modules/ti990hd.cpp b/src/tools/imgtool/modules/ti990hd.cpp
index 8edaeaf3fb6..a78589ff5aa 100644
--- a/src/tools/imgtool/modules/ti990hd.cpp
+++ b/src/tools/imgtool/modules/ti990hd.cpp
@@ -8,12 +8,15 @@
Raphael Nabet, 2003
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
#include "imgtool.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/* Max sector length is bytes. Generally 256, except for a few older disk
units which use 288-byte-long sectors, and SCSI units which generally use
standard 512-byte-long sectors. */
@@ -96,7 +99,7 @@ enum
Track 1 Sector 0 through N-2: optional disk program image loader
Track 1 Sector N-1: copy of Track 0 Sector 0
Track 1 Sector N: copy of Track 0 Sector 1
- Last cylinder has disagnostic information (reported as .S$DIAG)
+ Last cylinder has diagnostic information (reported as .S$DIAG)
Remaining sectors are used for fdr and data.
*/
@@ -214,7 +217,7 @@ struct ti990_fdr
UINT16BE hkc; /* hask key count: the number of file descriptor records that are present in the directory that hashed to this record number */
UINT16BE hkv; /* hask key value: the result of the hash algorithm for the file name actually covered in this record */
char fnm[8]; /* file name */
- uint8_t rsv[2]; /* reserved */
+ uint8_t rsv[2]; /* reserved */
UINT16BE fl1; /* flags word 1 */
UINT16BE flg; /* flags word 2 */
UINT16BE prs; /* physical record size */
@@ -227,31 +230,31 @@ struct ti990_fdr
UINT32BE eom; /* end of medium record number */
UINT32BE bkm; /* end of medium block number */
UINT16BE ofm; /* end of medium offset / */
- /* prelog number for KIF */
+ /* prelog number for KIF */
UINT32BE fbq; /* free block queue head */
UINT16BE btr; /* B-tree roots block # */
UINT32BE ebq; /* empty block queue head */
UINT16BE kdr; /* key descriptions record # */
- uint8_t ud[6]; /* last update date */
- uint8_t cd[6]; /* creation date */
- uint8_t apb; /* ADU's per block */
- uint8_t bpa; /* blocks per ADU */
- UINT16BE mrs; /* minimumu KIF record size */
- uint8_t sat[64]; /* secondary allocation table: 16 2-word entries. The first word of an entry contains the size, in ADUs, of the secondary allocation. The second word contains the starting ADU of the allocation. */
+ uint8_t ud[6]; /* last update date */
+ uint8_t cd[6]; /* creation date */
+ uint8_t apb; /* ADU's per block */
+ uint8_t bpa; /* blocks per ADU */
+ UINT16BE mrs; /* minimum KIF record size */
+ uint8_t sat[64]; /* secondary allocation table: 16 2-word entries. The first word of an entry contains the size, in ADUs, of the secondary allocation. The second word contains the starting ADU of the allocation. */
/* bytes >86 to >100 are optional */
- uint8_t res[10]; /* reserved: seem to be actually meaningful (at least under DX10 3.6.x) */
+ uint8_t res[10]; /* reserved: seem to be actually meaningful (at least under DX10 3.6.x) */
char uid[8]; /* user id of file creator */
UINT16BE psa; /* public security attribute */
ti990_ace ace[9]; /* 9 access control entries */
- uint8_t fil[2]; /* not used */
+ uint8_t fil[2]; /* not used */
};
/*
ADR record: variant of FDR for Aliases
The fields marked here with *** are in the ADR template to maintain
- compatability with the FDR template.
+ compatibility with the FDR template.
*/
struct ti990_adr
{
@@ -284,19 +287,19 @@ struct ti990_cdr
UINT16BE fill00; /* reserved */
UINT16BE fill01; /* reserved */
UINT16BE fdf; /* flags (same as fdr.flg) */
- uint8_t flg; /* channel flzgs */
- uint8_t iid; /* owner task installed ID */
- uint8_t typ; /* default resource type */
- uint8_t tf; /* resource type flags */
+ uint8_t flg; /* channel flzgs */
+ uint8_t iid; /* owner task installed ID */
+ uint8_t typ; /* default resource type */
+ uint8_t tf; /* resource type flags */
UINT16BE mxl; /* maximum message length */
- uint8_t fill04[6]; /* reserved (and, no, I don't know where fill02 and fill03 have gone) */
+ uint8_t fill04[6]; /* reserved (and, no, I don't know where fill02 and fill03 have gone) */
UINT16BE rna; /* record number of next CDR or ADR */
UINT16BE raf; /* record # of actual FDR */
- uint8_t fill05[110]; /* reserved */
+ uint8_t fill05[110]; /* reserved */
char uid[8]; /* user ID of channel creator */
UINT16BE psa; /* public security attribute */
- uint8_t scg[94]; /* "SDT with 9 control groups" (whatever it means - and, no, 94 is not dividable by 9) */
- uint8_t fill06[8]; /* reserved */
+ uint8_t scg[94]; /* "SDT with 9 control groups" (whatever it means - and, no, 94 is not dividable by 9) */
+ uint8_t fill06[8]; /* reserved */
};
/*
@@ -321,19 +324,18 @@ union directory_entry
*/
struct tifile_header
{
- char tifiles[8]; /* always '\7TIFILES' */
- uint8_t secsused_MSB; /* file length in sectors (big-endian) */
- uint8_t secsused_LSB;
- uint8_t flags; /* see enum above */
- uint8_t recspersec; /* records per sector */
- uint8_t eof; /* current position of eof in last sector (0->255)*/
- uint8_t reclen; /* bytes per record ([1,255] 0->256) */
- uint8_t fixrecs_MSB; /* file length in records (big-endian) */
- uint8_t fixrecs_LSB;
- uint8_t res[128-16]; /* reserved */
+ char tifiles[8]; /* always '\7TIFILES' */
+ uint8_t secsused_MSB; /* file length in sectors (big-endian) */
+ uint8_t secsused_LSB;
+ uint8_t flags; /* see enum above */
+ uint8_t recspersec; /* records per sector */
+ uint8_t eof; /* current position of eof in last sector (0->255)*/
+ uint8_t reclen; /* bytes per record ([1,255] 0->256) */
+ uint8_t fixrecs_MSB; /* file length in records (big-endian) */
+ uint8_t fixrecs_LSB;
+ uint8_t res[128-16]; /* reserved */
};
-
/*
catalog entry (used for in-memory catalog)
*/
@@ -398,11 +400,9 @@ static imgtoolerr_t ti990_image_beginenum(imgtool::directory &enumeration, const
static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent);
static void ti990_image_closeenum(imgtool::directory &enumeration);
static imgtoolerr_t ti990_image_freespace(imgtool::partition &partition, uint64_t *size);
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf);
-static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions);
-static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath);
-#endif
+[[maybe_unused]] static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf);
+[[maybe_unused]] static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions);
+[[maybe_unused]] static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath);
static imgtoolerr_t ti990_image_create(imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *createoptions);
enum
@@ -452,11 +452,10 @@ void ti990_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
}
}
-#ifdef UNUSED_FUNCTION
/*
Convert a C string to a 8-character file name (padded with spaces if necessary)
*/
-static void str_to_fname(char dst[8], const char *src)
+[[maybe_unused]] static void str_to_fname(char dst[8], const char *src)
{
int i;
@@ -478,7 +477,6 @@ static void str_to_fname(char dst[8], const char *src)
i++;
}
}
-#endif
/*
Convert a 8-character file name to a C string (removing trailing spaces if necessary)
@@ -555,7 +553,6 @@ static int read_sector_physical_len(imgtool::stream &file_handle, const ti990_ph
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
Read one sector from a disk image
@@ -564,11 +561,10 @@ static int read_sector_physical_len(imgtool::stream &file_handle, const ti990_ph
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
*/
-static int read_sector_physical(imgtool::stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest)
+[[maybe_unused]] static int read_sector_physical(imgtool::stream &file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest)
{
return read_sector_physical_len(file_handle, address, geometry, dest, geometry->bytes_per_sector);
}
-#endif
/*
Write one sector to a disk image
@@ -606,7 +602,6 @@ static int write_sector_physical_len(imgtool::stream &file_handle, const ti990_p
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
Write one sector to a disk image
@@ -615,11 +610,10 @@ static int write_sector_physical_len(imgtool::stream &file_handle, const ti990_p
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a source buffer of geometry->bytes_per_sector bytes
*/
-static int write_sector_physical(imgtool::stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src)
+[[maybe_unused]] static int write_sector_physical(imgtool::stream &file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src)
{
return write_sector_physical_len(file_handle, address, geometry, src, geometry->bytes_per_sector);
}
-#endif
/*
Convert logical sector address to physical sector address
@@ -651,7 +645,6 @@ static int read_sector_logical_len(imgtool::stream &file_handle, int secnum, con
return read_sector_physical_len(file_handle, &address, geometry, dest, len);
}
-#ifdef UNUSED_FUNCTION
/*
Read one sector from a disk image
@@ -660,11 +653,10 @@ static int read_sector_logical_len(imgtool::stream &file_handle, int secnum, con
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
*/
-static int read_sector_logical(imgtool::stream *file_handle, int secnum, const ti990_geometry *geometry, void *dest)
+[[maybe_unused]] static int read_sector_logical(imgtool::stream &file_handle, int secnum, const ti990_geometry *geometry, void *dest)
{
return read_sector_logical_len(file_handle, secnum, geometry, dest, geometry->bytes_per_sector);
}
-#endif
/*
Write one sector to a disk image
@@ -703,7 +695,6 @@ static int write_sector_logical(imgtool::stream &file_handle, int secnum, const
#pragma mark CATALOG FILE ROUTINES
#endif
-#ifdef UNUSED_FUNCTION
/*
Find the catalog entry and fdr record associated with a file name
@@ -715,7 +706,7 @@ static int write_sector_logical(imgtool::stream &file_handle, int secnum, const
out_parent_fdr_secnum: on output, sector offset of the fdr for the parent
directory fdr (-1 if root) (may be NULL)
*/
-static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *catalog_index, int *out_fdr_secnum, int *out_parent_fdr_secnum)
+static imgtoolerr_t find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *catalog_index, int *out_fdr_secnum, int *out_parent_fdr_secnum)
{
int fdr_secnum = -1, parent_fdr_secnum;
int i;
@@ -737,7 +728,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
do
{
/* read directory header */
- reply = read_sector_logical_len(image->file_handle, base, & image->geometry, &dor, sizeof(dor));
+ reply = read_sector_logical_len(*image->file_handle, base, & image->geometry, &dor, sizeof(dor));
if (reply)
return IMGTOOLERR_READERROR;
@@ -765,7 +756,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
i = hash_key;
while (1)
{
- reply = read_sector_logical_len(image->file_handle, base + i, & image->geometry,
+ reply = read_sector_logical_len(*image->file_handle, base + i, & image->geometry,
& xdr, 0x86);
if (reply)
return IMGTOOLERR_READERROR;
@@ -800,7 +791,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
if (flag & fdr_flg_ali)
{
/* read original fdr */
- reply = read_sector_logical_len(image->file_handle, base + get_UINT16BE(xdr.adr.raf),
+ reply = read_sector_logical_len(*image->file_handle, base + get_UINT16BE(xdr.adr.raf),
& image->geometry, & xdr, 0x86);
flag = get_UINT16BE(xdr.fdr.flg);
@@ -835,9 +826,8 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
if (out_parent_fdr_secnum)
*out_parent_fdr_secnum = parent_fdr_secnum;
- return 0;
+ return IMGTOOLERR_SUCCESS;
}
-#endif
#if 0
/*
@@ -1251,7 +1241,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
else
{
#if 0
- fname_to_str(ent.filename, iter->xdr[iter->level].fdr.fnm, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->xdr[iter->level].fdr.fnm, std::size(ent.filename));
#else
{
int i;
@@ -1261,11 +1251,11 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->xdr[i].fdr.fnm, 9);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->xdr[iter->level].fdr.fnm, 9);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
@@ -1273,7 +1263,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
flag = get_UINT16BE(iter->xdr[iter->level].fdr.flg);
if (flag & fdr_flg_cdr)
{
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "CHANNEL");
+ snprintf(ent.attr, std::size(ent.attr), "CHANNEL");
ent.filesize = 0;
}
@@ -1291,7 +1281,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
fname_to_str(buf, target_fdr.fnm, 9);
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "ALIAS OF %s", buf);
+ snprintf(ent.attr, std::size(ent.attr), "ALIAS OF %s", buf);
ent.filesize = 0;
}
@@ -1341,7 +1331,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
}
break;
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr),
+ snprintf(ent.attr, std::size(ent.attr),
"%s %c %s%s%s%s%s", fmt, (flag & fdr_flg_all) ? 'N' : 'C', type,
(flag & fdr_flg_blb) ? "" : " BLK",
(flag & fdr_flg_tmp) ? " TMP" : "",
@@ -1455,14 +1445,12 @@ static imgtoolerr_t ti990_image_freespace(imgtool::partition &partition, uint64_
return IMGTOOLERR_SUCCESS;
}
-#ifdef UNUSED_FUNCTION
/*
Extract a file from a ti990_image.
*/
static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1473,7 +1461,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1549,7 +1537,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
lnks_index++;
}
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
@@ -1558,8 +1546,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
*/
static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1571,7 +1558,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1673,7 +1660,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
return IMGTOOLERR_WRITEERROR;
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
@@ -1682,8 +1669,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
*/
static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1694,7 +1680,7 @@ static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1762,10 +1748,9 @@ static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const
if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
return IMGTOOLERR_WRITEERROR;
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
-#endif
/*
Create a blank ti990_image.
diff --git a/src/tools/imgtool/modules/vzdos.cpp b/src/tools/imgtool/modules/vzdos.cpp
index bf46863bb28..b7dee751434 100644
--- a/src/tools/imgtool/modules/vzdos.cpp
+++ b/src/tools/imgtool/modules/vzdos.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/****************************************************************************
@@ -8,15 +8,23 @@
****************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/vt_dsk.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "formats/vt_dsk_legacy.h"
+
+#include "corestr.h"
+#include "hashing.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/*
sector format
@@ -44,13 +52,22 @@ as track map, with one bit for each sector used.
/* vzdos directry entry */
struct vzdos_dirent
{
- char ftype;
- char delimitor;
- char fname[8];
+ struct {
+ char ftype;
+ char delimitor;
+ char fname[8];
+ } node;
uint8_t start_track;
uint8_t start_sector;
uint16_t start_address;
uint16_t end_address;
+
+ vzdos_dirent() :
+ start_track(0), start_sector(0),
+ start_address(0), end_address(0)
+ {
+ memset(&node, 0, sizeof(node));
+ }
};
struct vz_iterator
@@ -80,18 +97,6 @@ static int vzdos_get_fname_len(const char *fname)
return len;
}
-/* calculate checksum-16 of buffer */
-static uint16_t chksum16(uint8_t *buffer, int len)
-{
- int i;
- uint16_t sum = 0;
-
- for (i = 0; i < len; i++)
- sum += buffer[i];
-
- return sum;
-}
-
/* returns the offset where the actual sector data starts */
static imgtoolerr_t vzdos_get_data_start(imgtool::image &img, int track, int sector, int *start)
{
@@ -127,7 +132,7 @@ static imgtoolerr_t vzdos_read_sector_data(imgtool::image &img, int track, int s
if (ret) return (imgtoolerr_t)ret;
/* verify sector checksums */
- if (pick_integer_le(buffer, DATA_SIZE + 2, 2) != chksum16(buffer, DATA_SIZE + 2))
+ if (get_u16le(&buffer[DATA_SIZE + 2]) != util::sum16_creator::simple(buffer, DATA_SIZE + 2))
return IMGTOOLERR_CORRUPTFILE;
memcpy(data, &buffer, DATA_SIZE + 2);
@@ -145,7 +150,7 @@ static imgtoolerr_t vzdos_write_sector_data(imgtool::image &img, int track, int
if (ret) return (imgtoolerr_t)ret;
memcpy(buffer, data, DATA_SIZE + 2);
- place_integer_le(buffer, DATA_SIZE + 2, 2, chksum16(data, DATA_SIZE + 2));
+ put_u16le(&buffer[DATA_SIZE + 2], util::sum16_creator::simple(data, DATA_SIZE + 2));
ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, buffer, sizeof(buffer), 0); /* TODO: pass ddam argument from imgtool */
if (ret) return (imgtoolerr_t)ret;
@@ -157,8 +162,7 @@ static imgtoolerr_t vzdos_write_sector_data(imgtool::image &img, int track, int
static imgtoolerr_t vzdos_clear_sector(imgtool::image &img, int track, int sector)
{
uint8_t data[DATA_SIZE + 2];
-
- memset(data, 0x00, sizeof(data));
+ std::fill(std::begin(data), std::end(data), 0x00);
return vzdos_write_sector_data(img, track, sector, data);
}
@@ -166,21 +170,21 @@ static imgtoolerr_t vzdos_clear_sector(imgtool::image &img, int track, int secto
/* return a directory entry for an index */
static imgtoolerr_t vzdos_get_dirent(imgtool::image &img, int index, vzdos_dirent *ent)
{
- int ret, entry;
uint8_t buffer[DATA_SIZE + 2];
- ret = vzdos_read_sector_data(img, 0, (int) index / 8, buffer);
- if (ret) return (imgtoolerr_t)ret;
+ imgtoolerr_t const ret = vzdos_read_sector_data(img, 0, int(index) / 8, buffer);
+ if (IMGTOOLERR_SUCCESS != ret)
+ return ret;
- entry = ((index % 8) * sizeof(vzdos_dirent));
+ int const entry = ((index % 8) * sizeof(vzdos_dirent));
- memcpy(ent, &buffer[entry], 10);
- ent->start_track = pick_integer_le(&buffer[entry], 10, 1);
- ent->start_sector = pick_integer_le(&buffer[entry], 11, 1);
- ent->start_address = pick_integer_le(&buffer[entry], 12, 2);
- ent->end_address = pick_integer_le(&buffer[entry], 14, 2);
+ memcpy(&ent->node, &buffer[entry], 10);
+ ent->start_track = buffer[entry + 10];
+ ent->start_sector = buffer[entry + 11];
+ ent->start_address = get_u16le(&buffer[entry + 12]);
+ ent->end_address = get_u16le(&buffer[entry + 14]);
- if (ent->ftype == 0x00)
+ if (ent->node.ftype == 0x00)
return IMGTOOLERR_FILENOTFOUND;
/* check values */
@@ -206,10 +210,10 @@ static imgtoolerr_t vzdos_set_dirent(imgtool::image &img, int index, vzdos_diren
entry = ((index % 8) * sizeof(vzdos_dirent));
memcpy(&buffer[entry], &ent, 10);
- place_integer_le(buffer, entry + 10, 1, ent.start_track);
- place_integer_le(buffer, entry + 11, 1, ent.start_sector);
- place_integer_le(buffer, entry + 12, 2, ent.start_address);
- place_integer_le(buffer, entry + 14, 2, ent.end_address);
+ buffer[entry + 10] = ent.start_track;
+ buffer[entry + 11] = ent.start_sector;
+ put_u16le(&buffer[entry + 12], ent.start_address);
+ put_u16le(&buffer[entry + 14], ent.end_address);
/* save new sector */
ret = vzdos_write_sector_data(img, 0, (int) index / 8, buffer);
@@ -221,20 +225,12 @@ static imgtoolerr_t vzdos_set_dirent(imgtool::image &img, int index, vzdos_diren
/* clear a directory entry */
static imgtoolerr_t vzdos_clear_dirent(imgtool::image &img, int index)
{
- int ret;
vzdos_dirent entry;
-
- memset(&entry, 0x00, sizeof(vzdos_dirent));
-
- ret = vzdos_set_dirent(img, index, entry);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
+ return vzdos_set_dirent(img, index, entry);
}
/* search the index for a directory entry */
static imgtoolerr_t vzdos_searchentry(imgtool::image &image, const char *fname, int *entry) {
- int i, len, ret;
vzdos_dirent ent;
char filename[9];
@@ -246,23 +242,23 @@ static imgtoolerr_t vzdos_searchentry(imgtool::image &image, const char *fname,
*entry = -1;
- for (i = 0; i < MAX_DIRENTS; i++) {
- ret = vzdos_get_dirent(image, i, &ent);
- if (ret) return (imgtoolerr_t)ret;
+ for (int i = 0; i < MAX_DIRENTS; i++) {
+ imgtoolerr_t const ret = vzdos_get_dirent(image, i, &ent);
+ if (IMGTOOLERR_SUCCESS != ret)
+ return ret;
- len = vzdos_get_fname_len(ent.fname) + 1;
+ int const len = vzdos_get_fname_len(ent.node.fname) + 1;
if (strlen(fname) != len)
continue;
- memset(filename, 0x00, sizeof(filename));
- memcpy(filename, ent.fname, len);
+ std::fill(std::begin(filename), std::end(filename), 0x00);
+ memcpy(filename, ent.node.fname, len);
if (!core_stricmp(fname, filename)) {
*entry = i;
break;
}
-
}
if (*entry == -1)
@@ -359,7 +355,6 @@ static imgtoolerr_t vzdos_free_trackmap(imgtool::image &img, int *track, int *se
static imgtoolerr_t vzdos_write_formatted_sector(imgtool::image &img, int track, int sector)
{
- int ret;
uint8_t sector_data[DATA_SIZE + 4 + 24];
static const uint8_t sector_header[24] = {
@@ -368,15 +363,16 @@ static imgtoolerr_t vzdos_write_formatted_sector(imgtool::image &img, int track,
0x80, 0x80, 0x80, 0x00, 0xC3, 0x18, 0xE7, 0xFE
};
- memset(sector_data, 0x00, sizeof(sector_data));
+ std::fill(std::begin(sector_data), std::end(sector_data), 0x00);
memcpy(sector_data, sector_header, sizeof(sector_header));
sector_data[10] = (uint8_t) track; /* current track */
sector_data[11] = (uint8_t) sector; /* current sector */
sector_data[12] = (uint8_t) track + sector; /* checksum-8 */
- ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */
- if (ret) return (imgtoolerr_t)ret;
+ floperr_t const ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */
+ if (FLOPPY_ERROR_SUCCESS != ret)
+ return IMGTOOLERR_WRITEERROR;
return IMGTOOLERR_SUCCESS;
}
@@ -424,15 +420,15 @@ static imgtoolerr_t vzdos_diskimage_nextenum(imgtool::directory &enumeration, im
/* kill trailing spaces */
for (len = 7; len > 0; len--) {
- if (dirent.fname[len] != 0x20) {
+ if (dirent.node.fname[len] != 0x20) {
break;
}
}
- memcpy(ent.filename, &dirent.fname, len + 1);
+ memcpy(ent.filename, &dirent.node.fname, len + 1);
ent.filesize = dirent.end_address - dirent.start_address;
- switch (dirent.ftype)
+ switch (dirent.node.ftype)
{
case 0x01: type = "Deleted"; break;
case 'T': type = "Basic"; break;
@@ -445,7 +441,7 @@ static imgtoolerr_t vzdos_diskimage_nextenum(imgtool::directory &enumeration, im
default: type = "Unknown";
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%s", type);
+ snprintf(ent.attr, std::size(ent.attr), "%s", type);
iter->index++;
}
@@ -500,12 +496,12 @@ static imgtoolerr_t vzdos_diskimage_readfile(imgtool::partition &partition, cons
if (ret) return ret;
/* detect sectors pointing to themselfs */
- if ((track == (int)pick_integer_le(buffer, DATA_SIZE, 1)) && (sector == (int)pick_integer_le(buffer, DATA_SIZE + 1, 1)))
+ if ((track == (int)buffer[DATA_SIZE]) && (sector == (int)buffer[DATA_SIZE + 1]))
return IMGTOOLERR_CORRUPTIMAGE;
/* load next track and sector values */
- track = pick_integer_le(buffer, DATA_SIZE, 1);
- sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
+ track = buffer[DATA_SIZE];
+ sector = buffer[DATA_SIZE + 1];
/* track 0 is invalid */
if ((track == 0) && (filesize > DATA_SIZE))
@@ -581,8 +577,8 @@ static imgtoolerr_t vzdos_diskimage_deletefile(imgtool::partition &partition, co
if (ret) return ret;
/* load next track and sector values */
- next_track = pick_integer_le(buffer, DATA_SIZE, 1);
- next_sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
+ next_track = buffer[DATA_SIZE];
+ next_sector = buffer[DATA_SIZE + 1];
/* overwrite sector with default values */
ret = vzdos_clear_sector(img, track, sector);
@@ -617,8 +613,8 @@ static imgtoolerr_t vzdos_writefile(imgtool::partition &partition, int offset, i
return IMGTOOLERR_READONLY;
/* check for already existing filename -> overwrite */
- strcpy(filename, entry->fname);
- filename[vzdos_get_fname_len(entry->fname) + 1] = 0x00;
+ strcpy(filename, entry->node.fname);
+ filename[vzdos_get_fname_len(entry->node.fname) + 1] = 0x00;
ret = vzdos_get_dirent_fname(img, filename, &temp_entry);
if (!ret) {
/* file already exists, delete it */
@@ -702,8 +698,6 @@ static imgtoolerr_t vzdos_writefile(imgtool::partition &partition, int offset, i
/* create a new file or overwrite a file */
static imgtoolerr_t vzdos_diskimage_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
{
- imgtoolerr_t ret;
- int ftype;
vzdos_dirent entry;
/* TODO: check for leading spaces and strip */
@@ -711,37 +705,34 @@ static imgtoolerr_t vzdos_diskimage_writefile(imgtool::partition &partition, con
return IMGTOOLERR_BADFILENAME;
/* prepare directory entry */
- ftype = opts->lookup_int('T');
+ int const ftype = opts->lookup_int('T');
switch (ftype) {
case 0:
- entry.ftype = 'T';
+ entry.node.ftype = 'T';
entry.start_address = 31465;
break;
case 1:
- entry.ftype = 'B';
+ entry.node.ftype = 'B';
entry.start_address = 31465; /* ??? */
break;
case 2:
- entry.ftype = 'D';
+ entry.node.ftype = 'D';
entry.start_address = 31465; /* ??? */
break;
default:
break;
}
- entry.delimitor = ':';
- memset(&entry.fname, 0x20, 8); /* pad with spaces */
- memcpy(&entry.fname, filename, strlen(filename));
+ entry.node.delimitor = ':';
+ memset(&entry.node.fname, 0x20, 8); /* pad with spaces */
+ memcpy(&entry.node.fname, filename, strlen(filename));
/* write file to disk */
- ret = vzdos_writefile(partition, 0, sourcef, &entry);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
+ return vzdos_writefile(partition, 0, sourcef, &entry);
}
-static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t ret;
imgtool::image &image(partition.image());
@@ -751,37 +742,37 @@ static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partitio
ret = vzdos_get_dirent_fname(image, fname, &entry);
if (ret) return ret;
- switch (entry.ftype) {
+ switch (entry.node.ftype) {
case 'B':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_vzsnapshot_getinfo;
suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
suggestions[1].description = "Raw";
break;
case 'T':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_vzsnapshot_getinfo;
suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
suggestions[1].description = "Raw";
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_vzbas_getinfo;
suggestions[2].description = "Tokenized Basic";
break;
default:
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
suggestions[0].description = "Raw";
}
} else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
suggestions[0].description = "Raw";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_vzsnapshot_getinfo;
suggestions[1].description = "VZ Snapshot";
}
@@ -824,7 +815,7 @@ static imgtoolerr_t vzsnapshot_readfile(imgtool::partition &partition, const cha
header[1] = 'Z';
header[2] = 'F';
- switch (entry.ftype) {
+ switch (entry.node.ftype) {
case 'B':
header[3] = '1';
header[21] = 0xF1;
@@ -839,8 +830,8 @@ static imgtoolerr_t vzsnapshot_readfile(imgtool::partition &partition, const cha
}
memset(header + 4, 0x00, 17);
- memcpy(header + 4, entry.fname, vzdos_get_fname_len(entry.fname) + 1);
- place_integer_le(header, 22, 2, entry.start_address);
+ memcpy(header + 4, entry.node.fname, vzdos_get_fname_len(entry.node.fname) + 1);
+ put_u16le(&header[22], entry.start_address);
/* write header to file */
destf.write(header, sizeof(header));
@@ -863,21 +854,21 @@ static imgtoolerr_t vzsnapshot_writefile(imgtool::partition &partition, const ch
sourcef.read(header, sizeof(header));
/* prepare directory entry */
- entry.ftype = header[21] == 0xF1 ? 'B' : 'T';
- entry.delimitor = ':';
- entry.start_address = pick_integer_le(header, 22, 2);
+ entry.node.ftype = (header[21] == 0xF1) ? 'B' : 'T';
+ entry.node.delimitor = ':';
+ entry.start_address = get_u16le(&header[22]);
/* filename from header or directly? */
fnameopt = opts->lookup_int('F');
if (fnameopt == 0) {
- memcpy(&entry.fname, &header[4], 8);
+ memcpy(&entry.node.fname, &header[4], 8);
} else {
/* TODO: check for leading spaces and strip */
if (strlen(filename) > 8 || strlen(filename) < 1)
return IMGTOOLERR_BADFILENAME;
- memcpy(&entry.fname, filename, strlen(filename) - 3);
+ memcpy(&entry.node.fname, filename, strlen(filename) - 3);
}
/* write file to disk */
@@ -887,7 +878,7 @@ static imgtoolerr_t vzsnapshot_writefile(imgtool::partition &partition, const ch
return IMGTOOLERR_SUCCESS;
}
-void filter_vzsnapshot_getinfo(uint32_t state, union filterinfo *info)
+void filter_vzsnapshot_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
@@ -936,16 +927,16 @@ void vzdos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(vz_iterator); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "vzdos"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "VZ-DOS format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "T[0]-2;F[0]-1"); break;
- case IMGTOOLINFO_STR_EOLN: info->s = NULL; break;
+ case IMGTOOLINFO_STR_EOLN: info->s = nullptr; 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_OPEN: info->open = NULL; break;
+ case IMGTOOLINFO_PTR_OPEN: info->open = nullptr; break;
case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = vzdos_diskimage_beginenum; break;
case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = vzdos_diskimage_nextenum; break;
case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = vzdos_diskimage_freespace; break;