mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-09-28 02:55:03 +00:00
prodos: catalog works
This commit is contained in:
parent
18a286dc0d
commit
67814b316d
@ -21,6 +21,12 @@
|
|||||||
#define PRODOS_FILE_SUBDIR_HDR 0x0e
|
#define PRODOS_FILE_SUBDIR_HDR 0x0e
|
||||||
#define PRODOS_FILE_VOLUME_HDR 0x0f
|
#define PRODOS_FILE_VOLUME_HDR 0x0f
|
||||||
|
|
||||||
|
#define PRODOS_TYPE_TXT 0x04
|
||||||
|
#define PRODOS_TYPE_BIN 0x06
|
||||||
|
#define PRODOS_TYPE_BAS 0xFC
|
||||||
|
#define PRODOS_TYPE_VAR 0xFD
|
||||||
|
#define PRODOS_TYPE_SYS 0xFF
|
||||||
|
|
||||||
struct voldir_t {
|
struct voldir_t {
|
||||||
int fd;
|
int fd;
|
||||||
int interleave;
|
int interleave;
|
||||||
|
@ -7,194 +7,209 @@
|
|||||||
|
|
||||||
static int debug=0;
|
static int debug=0;
|
||||||
|
|
||||||
unsigned char prodos_file_type(int value) {
|
|
||||||
|
|
||||||
unsigned char result;
|
|
||||||
|
|
||||||
switch(value&0x7f) {
|
|
||||||
case 0x0: result='T'; break;
|
|
||||||
case 0x1: result='I'; break;
|
|
||||||
case 0x2: result='A'; break;
|
|
||||||
case 0x4: result='B'; break;
|
|
||||||
case 0x8: result='S'; break;
|
|
||||||
case 0x10: result='R'; break;
|
|
||||||
case 0x20: result='N'; break;
|
|
||||||
case 0x40: result='L'; break;
|
|
||||||
default: result='?'; break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char prodos_char_to_type(char type, int lock) {
|
|
||||||
|
|
||||||
unsigned char result=0,temp_type;
|
|
||||||
#if 0
|
|
||||||
temp_type=type;
|
|
||||||
/* Covert to upper case */
|
|
||||||
if (temp_type>='a') temp_type=temp_type-0x20;
|
|
||||||
|
|
||||||
switch(temp_type) {
|
|
||||||
case 'T': result=0x0; break;
|
|
||||||
case 'I': result=0x1; break;
|
|
||||||
case 'A': result=0x2; break;
|
|
||||||
case 'B': result=0x4; break;
|
|
||||||
case 'S': result=0x8; break;
|
|
||||||
case 'R': result=0x10; break;
|
|
||||||
case 'N': result=0x20; break;
|
|
||||||
case 'L': result=0x40; break;
|
|
||||||
default: result=0x0;
|
|
||||||
}
|
|
||||||
if (lock) result|=0x80;
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prodos filenames have top bit set on ascii chars */
|
|
||||||
/* and are padded with spaces */
|
|
||||||
char *prodos_filename_to_ascii(char *dest,unsigned char *src,int len) {
|
|
||||||
|
|
||||||
int i=0,last_nonspace=0;
|
|
||||||
|
|
||||||
for(i=0;i<len;i++) if (src[i]!=0xA0) last_nonspace=i;
|
|
||||||
|
|
||||||
for(i=0;i<last_nonspace+1;i++) {
|
|
||||||
dest[i]=src[i]^0x80; /* toggle top bit */
|
|
||||||
}
|
|
||||||
|
|
||||||
dest[i]='\0';
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a T/S value from a Catalog Sector */
|
|
||||||
static int prodos_get_catalog_ts(struct voldir_t *voldir) {
|
|
||||||
|
|
||||||
// return TS_TO_INT(voldir[VTOC_CATALOG_T],voldir[VTOC_CATALOG_S]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns the next valid catalog entry */
|
/* returns the next valid catalog entry */
|
||||||
/* after the one passed in */
|
/* after the one passed in */
|
||||||
static int prodos_find_next_file(int catalog_tsf,struct voldir_t *voldir) {
|
|
||||||
|
|
||||||
int catalog_track,catalog_sector,catalog_file;
|
/* inode = block<<8|entry */
|
||||||
int file_track,i;
|
|
||||||
int result;
|
|
||||||
unsigned char sector_buffer[PRODOS_BYTES_PER_BLOCK];
|
|
||||||
|
|
||||||
catalog_file=catalog_tsf>>16;
|
static int prodos_find_next_file(int inode, struct voldir_t *voldir) {
|
||||||
catalog_track=(catalog_tsf>>8)&0xff;
|
|
||||||
catalog_sector=(catalog_tsf&0xff);
|
|
||||||
|
|
||||||
if (debug) {
|
int result,catalog_block,catalog_offset;
|
||||||
fprintf(stderr,"CATALOG FIND NEXT, "
|
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
"CURRENT FILE=%X TRACK=%X SECTOR=%X\n",
|
int storage_type,file;
|
||||||
catalog_file,catalog_track,catalog_sector);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
catalog_loop:
|
|
||||||
|
|
||||||
/* Read in Catalog Sector */
|
catalog_block=inode>>8;
|
||||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
catalog_offset=inode&0xff;
|
||||||
result=read(fd,sector_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
catalog_offset++;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
/* Read in Sector */
|
||||||
|
result=prodos_read_block(voldir,catalog_buffer,catalog_block);
|
||||||
if (result<0) {
|
if (result<0) {
|
||||||
fprintf(stderr,"Error on I/O %s\n",strerror(errno));
|
fprintf(stderr,"Error on I/O\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i=catalog_file;
|
for(file=catalog_offset;
|
||||||
while(i<7) {
|
file<voldir->entries_per_block;file++) {
|
||||||
|
|
||||||
file_track=sector_buffer[CATALOG_FILE_LIST+
|
storage_type=(catalog_buffer[4+file*PRODOS_FILE_DESC_LEN]>>4)&0xf;
|
||||||
(i*CATALOG_ENTRY_SIZE)];
|
|
||||||
/* 0xff means file deleted */
|
if (storage_type!=PRODOS_FILE_DELETED) {
|
||||||
/* 0x0 means empty */
|
|
||||||
if (debug) {
|
return (catalog_block<<8)|file;
|
||||||
if (file_track==0xff) fprintf(stderr,"\tFILE %d DELETED\n",i);
|
}
|
||||||
if (file_track==0x00) fprintf(stderr,"\tFILE %d UNALLOCATED\n",i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((file_track!=0xff) && (file_track!=0x0)) {
|
catalog_offset=0;
|
||||||
if (debug) fprintf(stderr,"\tFOUND FILE %X TRACK $%X SECTOR $%X\n",i,catalog_track,catalog_sector);
|
catalog_block=catalog_buffer[2]|
|
||||||
return ((i<<16)+(catalog_track<<8)+catalog_sector);
|
(catalog_buffer[3]<<8);
|
||||||
}
|
if (catalog_block==0) break;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catalog_track=sector_buffer[CATALOG_NEXT_T];
|
|
||||||
catalog_sector=sector_buffer[CATALOG_NEXT_S];
|
|
||||||
|
|
||||||
if (debug) fprintf(stderr,"\tTRYING NEXT SECTOR T=$%X S=$%X\n",
|
|
||||||
catalog_track,catalog_sector);
|
|
||||||
|
|
||||||
/* FIXME: this wouldn't happen on 140k disks */
|
|
||||||
/* but who knows if you're doing something fancy? */
|
|
||||||
if ((catalog_track<0) || (catalog_track>40)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (catalog_sector!=0) {
|
|
||||||
catalog_file=0;
|
|
||||||
goto catalog_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prodos_print_file_info(int fd,int catalog_tsf) {
|
int prodos_populate_filedesc(unsigned char *file_desc,
|
||||||
|
struct file_entry_t *file_entry) {
|
||||||
|
|
||||||
int catalog_track,catalog_sector,catalog_file,i;
|
file_entry->storage_type=(file_desc[0]>>4)&0xf;
|
||||||
char temp_string[BUFSIZ];
|
file_entry->name_length=file_desc[0]&0xf;
|
||||||
int result;
|
memcpy(&file_entry->file_name[0],&file_desc[1],
|
||||||
unsigned char sector_buffer[PRODOS_BYTES_PER_BLOCK];
|
file_entry->name_length);
|
||||||
|
file_entry->file_name[file_entry->name_length]=0;
|
||||||
|
|
||||||
catalog_file=catalog_tsf>>16;
|
file_entry->file_type=file_desc[0x10];
|
||||||
catalog_track=(catalog_tsf>>8)&0xff;
|
file_entry->key_pointer=file_desc[0x11]|file_desc[0x12]<<8;
|
||||||
catalog_sector=(catalog_tsf&0xff);
|
file_entry->blocks_used=file_desc[0x13]|file_desc[0x14]<<8;
|
||||||
|
file_entry->eof=file_desc[0x15]|file_desc[0x16]<<8|
|
||||||
|
file_desc[0x17]<<16;
|
||||||
|
file_entry->creation_time=(file_desc[0x18]<<16)|
|
||||||
|
(file_desc[0x19]<<24)|
|
||||||
|
(file_desc[0x1a]<<0)|
|
||||||
|
(file_desc[0x1b]<<8);
|
||||||
|
file_entry->version=file_desc[0x1c];
|
||||||
|
file_entry->min_version=file_desc[0x1d];
|
||||||
|
file_entry->access=file_desc[0x1e];
|
||||||
|
file_entry->aux_type=file_desc[0x1f]|file_desc[0x20]<<8;
|
||||||
|
file_entry->last_mod=(file_desc[0x21]<<16)|
|
||||||
|
(file_desc[0x22]<<24)|
|
||||||
|
(file_desc[0x23]<<0)|
|
||||||
|
(file_desc[0x24]<<8);
|
||||||
|
file_entry->header_pointer=file_desc[0x25]|file_desc[0x26]<<8;
|
||||||
|
|
||||||
if (debug) fprintf(stderr,"CATALOG FILE=%X TRACK=%X SECTOR=%X\n",
|
return 0;
|
||||||
catalog_file,catalog_track,catalog_sector);
|
}
|
||||||
#if 0
|
|
||||||
/* Read in Catalog Sector */
|
|
||||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
|
||||||
result=read(fd,sector_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
if (sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f) {
|
static int prodos_print_short_filetype(int type) {
|
||||||
printf("*");
|
|
||||||
}
|
switch(type) {
|
||||||
else {
|
case 0x01: printf("BAD"); break; /* Bad Blocks */
|
||||||
printf(" ");
|
case 0x04: printf("TXT"); break; /* ASCII Text */
|
||||||
|
case 0x06: printf("BIN"); break; /* Binary */
|
||||||
|
case 0x0f: printf("DIR"); break; /* Directory */
|
||||||
|
case 0x19: printf("ADB"); break; /* Appleworks Database */
|
||||||
|
case 0x1A: printf("AWP"); break; /* Appleworks Word Processing */
|
||||||
|
case 0x1B: printf("ASP"); break; /* AppleWorks Spreadsheet */
|
||||||
|
case 0xEF: printf("PAS"); break; /* PASCAL */
|
||||||
|
case 0xF0: printf("CMD"); break; /* Command */
|
||||||
|
case 0xF1: case 0xF2: case 0xF3: case 0xF4:
|
||||||
|
case 0xF5: case 0xF6: case 0xF7: case 0xF8:
|
||||||
|
printf("USR"); break;
|
||||||
|
case 0xFC: printf("BAS"); break; /* Applesoft BASIC */
|
||||||
|
case 0xFD: printf("VAR"); break; /* Applesoft variables */
|
||||||
|
case 0xFE: printf("REL"); break; /* Relocatable Object */
|
||||||
|
case 0xFF: printf("SYS"); break; /* ProDOS system */
|
||||||
|
default:
|
||||||
|
case 0x00: printf("???"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%c",prodos_file_type(sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
|
|
||||||
printf(" ");
|
|
||||||
printf("%.3i ",sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
|
|
||||||
(sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
|
|
||||||
|
|
||||||
prodos_filename_to_ascii(temp_string,sector_buffer+(CATALOG_FILE_LIST+
|
return 0;
|
||||||
(catalog_file*CATALOG_ENTRY_SIZE+FILE_NAME)),30);
|
}
|
||||||
|
|
||||||
for(i=0;i<strlen(temp_string);i++) {
|
static unsigned char prodos_capital_month_names[12][4]={
|
||||||
if (temp_string[i]<0x20) {
|
"JAN","FEB","MAR","APR","MAY","JUN",
|
||||||
printf("^%c",temp_string[i]+0x40);
|
"JUL","AUG","SEP","OCT","NOV","DEC",
|
||||||
}
|
};
|
||||||
else {
|
|
||||||
printf("%c",temp_string[i]);
|
static int prodos_text_timestamp(int t, unsigned char *timestamp) {
|
||||||
|
|
||||||
|
int year,month,day,hour,minute;
|
||||||
|
|
||||||
|
year=(t>>25)&0x7f;
|
||||||
|
month=(t>>21)&0xf;
|
||||||
|
day=(t>>16)&0x1f;
|
||||||
|
hour=(t>>8)&0x1f;
|
||||||
|
minute=t&0x3f;
|
||||||
|
|
||||||
|
sprintf((char *)timestamp,"%2d-%s-%02d %2d:%02d",
|
||||||
|
day,prodos_capital_month_names[month-1],year,hour,minute);
|
||||||
|
timestamp[16]=0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int prodos_print_file_info(int inode, struct voldir_t *voldir) {
|
||||||
|
|
||||||
|
int result,catalog_block,catalog_offset;
|
||||||
|
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
|
unsigned char file_desc[PRODOS_FILE_DESC_LEN];
|
||||||
|
struct file_entry_t file_entry;
|
||||||
|
unsigned char timestamp[17];
|
||||||
|
|
||||||
|
catalog_block=inode>>8;
|
||||||
|
catalog_offset=inode&0xff;
|
||||||
|
|
||||||
|
/* Read in Sector */
|
||||||
|
result=prodos_read_block(voldir,catalog_buffer,catalog_block);
|
||||||
|
if (result<0) {
|
||||||
|
fprintf(stderr,"Error on I/O\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(file_desc,
|
||||||
|
catalog_buffer+4+catalog_offset*PRODOS_FILE_DESC_LEN,
|
||||||
|
PRODOS_FILE_DESC_LEN);
|
||||||
|
|
||||||
|
prodos_populate_filedesc(file_desc,&file_entry);
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
printf(" %-16s",file_entry.file_name);
|
||||||
|
|
||||||
|
/* type */
|
||||||
|
prodos_print_short_filetype(file_entry.file_type);
|
||||||
|
|
||||||
|
/* blocks used */
|
||||||
|
printf("%8d ",file_entry.blocks_used);
|
||||||
|
|
||||||
|
/* modified timestamp */
|
||||||
|
prodos_text_timestamp(file_entry.last_mod,timestamp);
|
||||||
|
printf("%s ",timestamp);
|
||||||
|
|
||||||
|
/* creation timestamp */
|
||||||
|
prodos_text_timestamp(file_entry.creation_time,timestamp);
|
||||||
|
printf("%s ",timestamp);
|
||||||
|
|
||||||
|
/* eof */
|
||||||
|
printf("%8d ",file_entry.eof);
|
||||||
|
|
||||||
|
switch(file_entry.file_type) {
|
||||||
|
|
||||||
|
// case PRODOS_TYPE_TXT:
|
||||||
|
// printf("L=$%04X",file_entry.aux_type);
|
||||||
|
// break;
|
||||||
|
case PRODOS_TYPE_BIN:
|
||||||
|
printf("A=$%04X",file_entry.aux_type);
|
||||||
|
break;
|
||||||
|
// case PRODOS_TYPE_BAS:
|
||||||
|
// printf("A=$%04X",file_entry.aux_type);
|
||||||
|
// break;
|
||||||
|
// case PRODOS_TYPE_VAR:
|
||||||
|
// printf("A=$%04X",file_entry.aux_type);
|
||||||
|
// break;
|
||||||
|
// case PRODOS_TYPE_SYS:
|
||||||
|
// printf("A=$%04X",file_entry.aux_type);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prodos_catalog(int dos_fd, struct voldir_t *voldir) {
|
void prodos_catalog(int dos_fd, struct voldir_t *voldir) {
|
||||||
|
|
||||||
int catalog_block,catalog_offset;
|
int catalog_block,catalog_offset,catalog_inode;
|
||||||
int blocks_free=0;
|
int blocks_free=0;
|
||||||
|
|
||||||
blocks_free=prodos_voldir_free_space(voldir);
|
blocks_free=prodos_voldir_free_space(voldir);
|
||||||
@ -206,11 +221,13 @@ void prodos_catalog(int dos_fd, struct voldir_t *voldir) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
catalog_block=PRODOS_VOLDIR_KEY_BLOCK;
|
catalog_block=PRODOS_VOLDIR_KEY_BLOCK;
|
||||||
catalog_offset=1; /* skip the header */
|
catalog_offset=0; /* skip the header */
|
||||||
|
catalog_inode=(catalog_block<<8)|catalog_offset;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
catalog_offset=prodos_find_next_file(catalog_offset,voldir);
|
catalog_inode=prodos_find_next_file(catalog_inode,voldir);
|
||||||
if (catalog_offset<0) break;
|
if (catalog_inode==-1) break;
|
||||||
|
prodos_print_file_info(catalog_inode,voldir);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -218,5 +235,5 @@ void prodos_catalog(int dos_fd, struct voldir_t *voldir) {
|
|||||||
printf(" BLOCKS USED: % 3d ",voldir->total_blocks-blocks_free);
|
printf(" BLOCKS USED: % 3d ",voldir->total_blocks-blocks_free);
|
||||||
printf(" TOTAL BLOCKS: % 3d ",voldir->total_blocks);
|
printf(" TOTAL BLOCKS: % 3d ",voldir->total_blocks);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user