prodos: add subdir support to DUMP

This commit is contained in:
Vince Weaver 2021-08-04 00:59:46 -04:00
parent b2e684247b
commit 1907caf2c4
5 changed files with 191 additions and 28 deletions

View File

@ -23,7 +23,6 @@ TODO:
prodos:
test! especially tree (files bigger than 128k)
subdirectory support
delete support
support for setting attributes

View File

@ -432,7 +432,7 @@ static int prodos_add_file(struct voldir_t *voldir,
file.creation_time=prodos_time(time(NULL));
file.version=0;
file.min_version=0;
file.access=0;
file.access=0xe3; // 0x21?
file.aux_type=0;
file.last_mod=prodos_time(time(NULL));
file.header_pointer=PRODOS_VOLDIR_KEY_BLOCK;
@ -880,6 +880,8 @@ static void display_help(char *name, int version_only) {
printf("\tRENAME apple_file_old apple_file_new\n");
printf("\tDUMP\n");
printf("\tVOLUME volume_name\n");
printf("\tMKDIR dir_name\n");
printf("\tRMDIR dir_name\n");
printf("\tTYPE TODO: set type\n");
printf("\tAUX TODO: set aux\n");
printf("\tTIMESTAMP TODO: set timestamp\n");
@ -897,8 +899,10 @@ static void display_help(char *name, int version_only) {
#define COMMAND_DUMP 5
#define COMMAND_SHOWFREE 6
#define COMMAND_VOLNAME 7
#define COMMAND_MKDIR 8
#define COMMAND_RMDIR 9
#define MAX_COMMAND 8
#define MAX_COMMAND 10
#define COMMAND_UNKNOWN 255
static struct command_type {
@ -913,6 +917,8 @@ static struct command_type {
{COMMAND_DUMP,"DUMP"},
{COMMAND_SHOWFREE,"SHOWFREE"},
{COMMAND_VOLNAME,"VOLNAME"},
{COMMAND_MKDIR,"MKDIR"},
{COMMAND_RMDIR,"RMDIR"},
};
static int lookup_command(char *name) {
@ -1314,12 +1320,12 @@ int main(int argc, char **argv) {
case COMMAND_DUMP:
printf("Dumping %s!\n",image);
prodos_dump(&voldir,prodos_fd);
prodos_dump(&voldir);
break;
case COMMAND_SHOWFREE:
printf("Showing Free %s!\n",image);
prodos_showfree(&voldir,prodos_fd);
prodos_showfree(&voldir);
break;
case COMMAND_RENAME:

View File

@ -28,6 +28,15 @@
#define PRODOS_TYPE_VAR 0xFD
#define PRODOS_TYPE_SYS 0xFF
/* Normal access is $C3 */
/* Locked file is $01 */
/* Non-empty directories often locked? */
#define PRODOS_ACCESS_DESTROY 0x80 // can be deleted
#define PRODOS_ACCESS_RENAME 0x40
#define PRODOS_ACCESS_CHANGED 0x20 // has been changed since last backup
#define PRODOS_ACCESS_WRITE 0x02
#define PRODOS_ACCESS_READ 0x01
struct voldir_t {
int fd;
int interleave;
@ -47,6 +56,26 @@ struct voldir_t {
unsigned int creation_time;
};
struct subdir_t {
unsigned char storage_type;
unsigned char name_length;
unsigned char version;
unsigned char min_version;
unsigned char access;
unsigned char entry_length;
unsigned char entries_per_block;
unsigned char parent_entry;
unsigned char parent_entry_length;
unsigned short file_count;
unsigned short parent_pointer;
// unsigned short next_block;
// unsigned short bit_map_pointer;
// unsigned short total_blocks;
unsigned char subdir_name[16];
unsigned int creation_time;
};
struct file_entry_t {
unsigned char storage_type;
unsigned char name_length;
@ -81,8 +110,8 @@ void prodos_catalog(int dos_fd, struct voldir_t *voldir);
//unsigned char prodos_file_type(int value);
/* prodos_dump.c */
int prodos_dump(struct voldir_t *voldir, int fd);
int prodos_showfree(struct voldir_t *voldir, int fd);
int prodos_dump(struct voldir_t *voldir);
int prodos_showfree(struct voldir_t *voldir);
/* prodos_read.c */
int prodos_read_block(struct voldir_t *voldir,unsigned char *block, int blocknum);

View File

@ -6,7 +6,7 @@
#include "prodos.h"
//static int debug=0;
extern int debug;
/* returns the next valid catalog entry */

View File

@ -10,6 +10,8 @@
#include "prodos.h"
extern int debug;
#if 0
static int dump_block(unsigned char *block_buffer) {
@ -56,11 +58,11 @@ static void prodos_print_time(int t) {
static void prodos_print_access(int access) {
if (access&0x80) printf("DESTROY ");
if (access&0x40) printf("RENAME ");
if (access&0x20) printf("VOLDIR_NEW ");
if (access&0x2) printf("VOLDIR_WRITE ");
if (access&0x1) printf("VOLDIR_READ ");
if (access&PRODOS_ACCESS_DESTROY) printf("DESTROY ");
if (access&PRODOS_ACCESS_RENAME) printf("RENAME ");
if (access&PRODOS_ACCESS_CHANGED) printf("CHANGED ");
if (access&PRODOS_ACCESS_WRITE) printf("WRITE ");
if (access&PRODOS_ACCESS_READ) printf("READ ");
}
@ -183,40 +185,79 @@ static void dump_voldir(struct voldir_t *voldir) {
}
int prodos_dump(struct voldir_t *voldir, int fd) {
int prodos_dump_subdir(struct voldir_t *voldir, int subdir_key_block) {
int catalog_block,catalog_offset,file;
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
unsigned char subdir_buffer[PRODOS_BYTES_PER_BLOCK];
unsigned char file_desc[PRODOS_FILE_DESC_LEN];
int result;
struct file_entry_t file_entry;
struct subdir_t subdir;
int subdir_block,subdir_offset,file;
dump_voldir(voldir);
printf("\n");
printf("Dumping subdir at $%X\n",subdir_key_block);
prodos_voldir_dump_bitmap(voldir);
result=prodos_read_block(voldir,subdir_buffer,subdir_key_block);
catalog_block=PRODOS_VOLDIR_KEY_BLOCK;
catalog_offset=1; /* skip the header */
subdir.storage_type=subdir_buffer[0x04]>>4;
subdir.name_length=subdir_buffer[0x04]&0xf;
memcpy(subdir.subdir_name,&subdir_buffer[0x05],15);
subdir.subdir_name[subdir.name_length]=0;
/* note 0x14 must be $75??? */
subdir.creation_time=(subdir_buffer[0x1c]<<16)|
(subdir_buffer[0x1d]<<24)|
(subdir_buffer[0x1e]<<0)|
(subdir_buffer[0x1f]<<8);
subdir.version=subdir_buffer[0x20];
subdir.min_version=subdir_buffer[0x21];
subdir.access=subdir_buffer[0x22];
subdir.entry_length=subdir_buffer[0x23];
subdir.entries_per_block=subdir_buffer[0x24];
subdir.file_count=(subdir_buffer[0x25]|(subdir_buffer[0x26]<<8));
subdir.parent_pointer=(subdir_buffer[0x27]|(subdir_buffer[0x28]<<8));
subdir.parent_entry=subdir_buffer[0x29];
subdir.parent_entry_length=subdir_buffer[0x2A];
printf("\tStorage type: ($%x): ",subdir.storage_type);
prodos_print_storage_type(subdir.storage_type);
printf("\tName length: $%x\n",subdir.name_length);
printf("\tName: %s\n",subdir.subdir_name);
printf("\tCreation Time (%x): ",subdir.creation_time);
prodos_print_time(subdir.creation_time);
printf("\n");
printf("\tVersion: %d\n",subdir.version);
printf("\tMin Version: %d\n",subdir.min_version);
printf("\tAccess (%x): ",subdir.access);
prodos_print_access(subdir.access);
printf("\n");
printf("\tEntry length: %d\n",subdir.entry_length);
printf("\tEntries per block: %d\n",subdir.entries_per_block);
printf("\tFile count: %d\n",subdir.file_count);
printf("\tParent Pointer: $%x\n",subdir.parent_pointer);
printf("\tParent Entry: $%x\n",subdir.parent_entry);
printf("\tParent Entry Length: $%x\n",subdir.parent_entry_length);
subdir_block=subdir_key_block;
subdir_offset=1; /* skip the header */
while(1) {
result=prodos_read_block(voldir,catalog_buffer,catalog_block);
result=prodos_read_block(voldir,subdir_buffer,subdir_block);
if (result<0) fprintf(stderr,"Error on I/O\n");
// dump_block(catalog_buffer);
for(file=catalog_offset;
file<voldir->entries_per_block;file++) {
for(file=subdir_offset;
file<subdir.entries_per_block;file++) {
memcpy(file_desc,
catalog_buffer+4+file*PRODOS_FILE_DESC_LEN,
subdir_buffer+4+file*PRODOS_FILE_DESC_LEN,
PRODOS_FILE_DESC_LEN);
prodos_populate_filedesc(file_desc,&file_entry);
if (file_entry.storage_type==PRODOS_FILE_DELETED) continue;
printf("\n\n");
printf("FILE %d: %s\n",file,file_entry.file_name);
printf("FILE $%X-%d: %s\n",subdir_block,file,file_entry.file_name);
printf("\t");
prodos_print_storage_type(file_entry.storage_type);
@ -251,6 +292,92 @@ int prodos_dump(struct voldir_t *voldir, int fd) {
}
/* move to next */
subdir_block=subdir_buffer[0x2]|(subdir_buffer[0x3]<<8);
if (subdir_block==0) break;
subdir_offset=0;
}
printf("\n");
return 0;
}
int prodos_dump(struct voldir_t *voldir) {
int catalog_block,catalog_offset,file;
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
unsigned char file_desc[PRODOS_FILE_DESC_LEN];
int result;
struct file_entry_t file_entry;
dump_voldir(voldir);
prodos_voldir_dump_bitmap(voldir);
catalog_block=PRODOS_VOLDIR_KEY_BLOCK;
catalog_offset=1; /* skip the header */
while(1) {
result=prodos_read_block(voldir,catalog_buffer,catalog_block);
if (result<0) fprintf(stderr,"Error on I/O\n");
// dump_block(catalog_buffer);
for(file=catalog_offset;
file<voldir->entries_per_block;file++) {
memcpy(file_desc,
catalog_buffer+4+file*PRODOS_FILE_DESC_LEN,
PRODOS_FILE_DESC_LEN);
prodos_populate_filedesc(file_desc,&file_entry);
if (file_entry.storage_type==PRODOS_FILE_DELETED) continue;
printf("\n\n");
printf("FILE %d: %s\n",file,file_entry.file_name);
printf("\t($%X): ",file_entry.storage_type);
prodos_print_storage_type(file_entry.storage_type);
printf("\t");
prodos_print_file_type(file_entry.file_type);
printf("\tKey pointer: $%x\n",file_entry.key_pointer);
printf("\tBlocks Used: %d\n",file_entry.blocks_used);
printf("\tFile size (eof): %d\n",file_entry.eof);
printf("\tCreation Time (%x): ",file_entry.creation_time);
prodos_print_time(file_entry.creation_time);
printf("\n");
printf("\tVersion: %d\n",file_entry.version);
printf("\tMin Version: %d\n",file_entry.min_version);
printf("\tAccess (%x): ",file_entry.access);
prodos_print_access(file_entry.access);
printf("\n");
printf("\tAux Type: %x\n",file_entry.aux_type);
printf("\tLast mod Time: (%x) ",file_entry.last_mod);
prodos_print_time(file_entry.last_mod);
printf("\n");
printf("\tHeader pointer: %x\n",file_entry.header_pointer);
if (file_entry.storage_type==PRODOS_FILE_SUBDIR) {
prodos_dump_subdir(voldir,file_entry.key_pointer);
}
}
/* move to next */
catalog_block=catalog_buffer[0x2]|(catalog_buffer[0x3]<<8);
if (catalog_block==0) break;
@ -264,7 +391,9 @@ int prodos_dump(struct voldir_t *voldir, int fd) {
return 0;
}
int prodos_showfree(struct voldir_t *voldir, int fd) {
int prodos_showfree(struct voldir_t *voldir) {
#if 0
int num_tracks,catalog_t,catalog_s,file,ts_t,ts_s,ts_total;
int track,sector;