dos33fsprogs/utils/prodos-utils/prodos_catalog.c
2021-08-04 15:35:50 -04:00

249 lines
6.1 KiB
C

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "prodos.h"
extern int debug;
/* returns the next valid catalog entry */
/* after the one passed in */
/* inode = block<<8|entry */
int prodos_find_next_file(int inode, struct voldir_t *voldir) {
int result,catalog_block,catalog_offset;
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
int storage_type,file;
catalog_block=inode>>8;
catalog_offset=inode&0xff;
catalog_offset++;
while(1) {
/* Read in Sector */
result=prodos_read_block(voldir,catalog_buffer,catalog_block);
if (result<0) {
fprintf(stderr,"Error on I/O\n");
return -1;
}
for(file=catalog_offset;
file<voldir->entries_per_block;file++) {
storage_type=(catalog_buffer[4+file*PRODOS_FILE_DESC_LEN]>>4)&0xf;
if (storage_type!=PRODOS_FILE_DELETED) {
return (catalog_block<<8)|file;
}
}
catalog_offset=0;
catalog_block=catalog_buffer[2]|
(catalog_buffer[3]<<8);
if (catalog_block==0) break;
}
return -1;
}
int prodos_populate_filedesc(unsigned char *file_desc,
struct file_entry_t *file_entry) {
file_entry->storage_type=(file_desc[0]>>4)&0xf;
file_entry->name_length=file_desc[0]&0xf;
memcpy(&file_entry->file_name[0],&file_desc[1],
file_entry->name_length);
file_entry->file_name[file_entry->name_length]=0;
file_entry->file_type=file_desc[0x10];
file_entry->key_pointer=file_desc[0x11]|file_desc[0x12]<<8;
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;
return 0;
}
static int prodos_print_short_filetype(int type) {
switch(type) {
case 0x01: printf("BAD"); break; /* Bad Blocks */
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;
}
return 0;
}
static unsigned char prodos_capital_month_names[13][4]={
"???",
"JAN","FEB","MAR","APR","MAY","JUN",
"JUL","AUG","SEP","OCT","NOV","DEC",
};
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],year%100,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("%c%-16s",(file_entry.access&PRODOS_ACCESS_WRITE)?' ':'*',
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");
return 0;
}
void prodos_catalog(struct voldir_t *voldir, int dir_block,char *path) {
int catalog_block,catalog_offset,catalog_inode;
int blocks_free=0;
blocks_free=prodos_voldir_free_space(voldir);
printf("\n");
if (path==NULL) {
printf("/%s\n\n",voldir->volume_name);
}
else {
printf("/%s/%s\n\n",voldir->volume_name,path);
}
printf(" NAME TYPE BLOCKS MODIFIED CREATED ENDFILE SUBTYPE\n");
printf("\n");
catalog_block=dir_block;
catalog_offset=0; /* skip the header */
catalog_inode=(catalog_block<<8)|catalog_offset;
while(1) {
catalog_inode=prodos_find_next_file(catalog_inode,voldir);
if (catalog_inode==-1) break;
prodos_print_file_info(catalog_inode,voldir);
}
printf("\n");
printf("BLOCKS FREE: % 3d ",blocks_free);
printf(" BLOCKS USED: % 3d ",voldir->total_blocks-blocks_free);
printf(" TOTAL BLOCKS: % 3d ",voldir->total_blocks);
printf("\n\n");
}