mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-29 00:31:52 +00:00
249 lines
6.1 KiB
C
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");
|
|
}
|