dos33fsprogs/utils/dos33fs-utils/dos33_catalog.c

218 lines
5.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "dos33.h"
unsigned char dos33_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 dos33_char_to_type(char type, int lock) {
unsigned char result,temp_type;
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;
return result;
}
/* dos33 filenames have top bit set on ascii chars */
/* and are padded with spaces */
char *dos33_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 dos33_get_catalog_ts(unsigned char *vtoc) {
return TS_TO_INT(vtoc[VTOC_CATALOG_T],vtoc[VTOC_CATALOG_S]);
}
/* returns the next valid catalog entry */
/* after the one passed in */
static int dos33_find_next_file(int fd,int catalog_tsf,unsigned char *vtoc) {
int catalog_track,catalog_sector,catalog_file;
int file_track,i;
int result;
unsigned char sector_buffer[BYTES_PER_SECTOR];
catalog_file=catalog_tsf>>16;
catalog_track=(catalog_tsf>>8)&0xff;
catalog_sector=(catalog_tsf&0xff);
if (debug) {
fprintf(stderr,"CATALOG FIND NEXT, "
"CURRENT FILE=%X TRACK=%X SECTOR=%X\n",
catalog_file,catalog_track,catalog_sector);
}
catalog_loop:
/* Read in Catalog Sector */
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
result=read(fd,sector_buffer,BYTES_PER_SECTOR);
if (result<0) {
fprintf(stderr,"Error on I/O %s\n",strerror(errno));
return -1;
}
i=catalog_file;
while(i<7) {
file_track=sector_buffer[CATALOG_FILE_LIST+
(i*CATALOG_ENTRY_SIZE)];
/* 0xff means file deleted */
/* 0x0 means empty */
if (debug) {
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)) {
if (debug) fprintf(stderr,"\tFOUND FILE %X TRACK $%X SECTOR $%X\n",i,catalog_track,catalog_sector);
return ((i<<16)+(catalog_track<<8)+catalog_sector);
}
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;
}
return -1;
}
static int dos33_print_file_info(int fd,int catalog_tsf) {
int catalog_track,catalog_sector,catalog_file,i;
char temp_string[BUFSIZ];
int result;
unsigned char sector_buffer[BYTES_PER_SECTOR];
catalog_file=catalog_tsf>>16;
catalog_track=(catalog_tsf>>8)&0xff;
catalog_sector=(catalog_tsf&0xff);
if (debug) fprintf(stderr,"CATALOG FILE=%X TRACK=%X SECTOR=%X\n",
catalog_file,catalog_track,catalog_sector);
/* Read in Catalog Sector */
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
result=read(fd,sector_buffer,BYTES_PER_SECTOR);
if (result<BYTES_PER_SECTOR) {
fprintf(stderr,"Error on I/O\n");
return -ERROR_FILE_READ;
}
if (sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f) {
printf("*");
}
else {
printf(" ");
}
printf("%c",dos33_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));
dos33_filename_to_ascii(temp_string,sector_buffer+(CATALOG_FILE_LIST+
(catalog_file*CATALOG_ENTRY_SIZE+FILE_NAME)),30);
for(i=0;i<strlen(temp_string);i++) {
if (temp_string[i]<0x20) {
printf("^%c",temp_string[i]+0x40);
}
else {
printf("%c",temp_string[i]);
}
}
printf("\n");
return 0;
}
int dos33_catalog(int dos_fd, unsigned char *vtoc) {
int catalog_entry;
int result;
/* get first catalog */
catalog_entry=dos33_get_catalog_ts(vtoc);
printf("\nDISK VOLUME %i\n\n",vtoc[VTOC_DISK_VOLUME]);
while(catalog_entry>0) {
catalog_entry=dos33_find_next_file(dos_fd,catalog_entry,vtoc);
if (debug) fprintf(stderr,"CATALOG entry=$%X\n",catalog_entry);
if (catalog_entry>0) {
result=dos33_print_file_info(dos_fd,catalog_entry);
if (result<0) return result;
/* why 1<<16 ? */
catalog_entry+=(1<<16);
/* dos33_find_next_file() handles wrapping issues */
}
}
printf("\n");
return 0;
}