mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-27 02:31:00 +00:00
prodos: mkprodosfs vaguely working
This commit is contained in:
parent
5e04bbf227
commit
2e0f87162f
@ -10,12 +10,14 @@ prodos: prodos.o \
|
||||
prodos_read.o \
|
||||
prodos_catalog.o \
|
||||
prodos_dump.o \
|
||||
prodos_volume_bitmap.o
|
||||
prodos_volume_bitmap.o \
|
||||
prodos_voldir.o
|
||||
$(CC) -o prodos prodos.o \
|
||||
prodos_read.o \
|
||||
prodos_catalog.o \
|
||||
prodos_dump.o \
|
||||
prodos_volume_bitmap.o $(LFLAGS)
|
||||
prodos_volume_bitmap.o \
|
||||
prodos_voldir.o $(LFLAGS)
|
||||
|
||||
prodos.o: prodos.c prodos.h
|
||||
$(CC) $(CFLAGS) -g -c prodos.c
|
||||
@ -46,9 +48,11 @@ text_to_prodos.o: text_to_prodos.c
|
||||
|
||||
###
|
||||
|
||||
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o
|
||||
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o \
|
||||
prodos_voldir.o
|
||||
$(CC) $(LFLAGS) -o mkprodosfs mkprodosfs.o \
|
||||
prodos_read.o prodos_volume_bitmap.o
|
||||
prodos_read.o prodos_volume_bitmap.o \
|
||||
prodos_voldir.o
|
||||
|
||||
mkprodosfs.o: mkprodosfs.c prodos.h
|
||||
$(CC) $(CFLAGS) -c mkprodosfs.c
|
||||
@ -75,6 +79,12 @@ prodos_read.o: prodos_read.c prodos.h
|
||||
|
||||
###
|
||||
|
||||
prodos_voldir.o: prodos_voldir.c prodos.h
|
||||
$(CC) $(CFLAGS) -c prodos_voldir.c
|
||||
|
||||
|
||||
###
|
||||
|
||||
|
||||
install:
|
||||
cp prodos mkprodosfs prodoscat text_to_prodos $(INSTALL_LOC)
|
||||
|
@ -9,7 +9,11 @@
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
int debug=0;
|
||||
int debug=1;
|
||||
|
||||
static int ones_lookup[8]={
|
||||
0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
static void usage(char *binary,int help) {
|
||||
|
||||
@ -17,15 +21,12 @@ static void usage(char *binary,int help) {
|
||||
printf("\tby Vince Weaver <vince@deater.net>\n");
|
||||
printf("\thttp://www.deater.net/weave/vmwprod/apple/\n\n");
|
||||
if (help) {
|
||||
printf("Usage:\t%s [-t track] [-s sector] [-b size] "
|
||||
"[-d filename] [-f filename] device_name\n\n",binary);
|
||||
printf("\t-t tracks : number of tracks (default is 35)\n");
|
||||
printf("\t-s sectors : number of sectors (default is 16)\n");
|
||||
printf("\t-b blocksize : size of sector, in bytes (default is 256)\n");
|
||||
printf("\t-d filename : file to copy first 3 tracks over from\n");
|
||||
printf("\t-f filename : name of BASIC file to autoboot. Default is HELLO\n");
|
||||
printf("\t-m maxfiles : maximum files in CATALOG (default is 105)\n");
|
||||
printf("\t-n volume : volume number (default is 254)\n");
|
||||
printf("Usage:\t%s [-b size] [-i interleave] "
|
||||
"[-s bootsector] device_name\n\n",binary);
|
||||
printf("\t-b size : size of image, in 512B blocks\n");
|
||||
printf("\t-i interleave : PRODOS (default) or DOS33\n");
|
||||
printf("\t-s filename : bootsector\n");
|
||||
printf("\t-n volume : volume name\n");
|
||||
printf("\n\n");
|
||||
}
|
||||
exit(0);
|
||||
@ -34,61 +35,52 @@ static void usage(char *binary,int help) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int num_tracks=35,num_sectors=16,sector_size=256;
|
||||
int max_files=105,catalog_track=17,vtoc_track=17,volume_number=254;
|
||||
int catalog_sectors,current_sector;
|
||||
int max_ts_pairs=255;
|
||||
int fd,dos_fd;
|
||||
char device[BUFSIZ],dos_src[BUFSIZ];
|
||||
unsigned char *vtoc_buffer=NULL,*sector_buffer=NULL;
|
||||
int num_blocks=280;
|
||||
int fd;
|
||||
char device[BUFSIZ];
|
||||
char *endptr;
|
||||
int i,c,copy_dos=0;
|
||||
int i,j,c;
|
||||
int result;
|
||||
unsigned char data_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||
struct voldir_t voldir;
|
||||
char volname[PRODOS_VOLNAME_LEN];
|
||||
int volname_len;
|
||||
int interleave=PRODOS_INTERLEAVE_PRODOS;
|
||||
int num_voldirs=4,num_bitmaps,num_bitmap_blocks,ones_to_write;
|
||||
|
||||
char boot_filename[30]="HELLO ";
|
||||
strncpy(volname,"EMPTY",6);
|
||||
volname_len=strlen(volname);
|
||||
|
||||
/* Parse Command Line Arguments */
|
||||
|
||||
while ((c = getopt (argc, argv,"t:s:b:d:f:m:n:hv"))!=-1) {
|
||||
while ((c = getopt (argc, argv,"b:i:s:n:hv"))!=-1) {
|
||||
switch (c) {
|
||||
|
||||
case 't':
|
||||
num_tracks=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
num_sectors=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
sector_size=strtol(optarg,&endptr,10);
|
||||
num_blocks=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
max_files=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
volume_number=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
copy_dos=1;
|
||||
strncpy(dos_src,optarg,BUFSIZ-1);
|
||||
break;
|
||||
case 'f':
|
||||
if (strlen(optarg)>30) {
|
||||
fprintf(stderr,"Auto boot filename too long!\n");
|
||||
exit(1);
|
||||
case 'i':
|
||||
if (!strncasecmp(optarg,"prodos",6)) {
|
||||
interleave=PRODOS_INTERLEAVE_PRODOS;
|
||||
}
|
||||
memcpy(boot_filename,optarg,strlen(optarg));
|
||||
for(i=strlen(optarg);i<30;i++) boot_filename[i]=' ';
|
||||
// printf("Writing boot filename \"%s\"\n",boot_filename);
|
||||
else if (!strncasecmp(optarg,"dos33",5)) {
|
||||
interleave=PRODOS_INTERLEAVE_DOS33;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"Error! Unknown interleave: %s\n",optarg);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
fprintf(stderr,"Error! -s not implemented yet!\n");
|
||||
break;
|
||||
case 'n':
|
||||
memset(volname,0,sizeof(volname));
|
||||
volname_len=strlen(optarg);
|
||||
if (volname_len>PRODOS_VOLNAME_LEN) {
|
||||
fprintf(stderr,"Volname: %s is too long!\n",optarg);
|
||||
return -1;
|
||||
}
|
||||
memcpy(volname,optarg,volname_len);
|
||||
break;
|
||||
case 'v': usage(argv[0],0);
|
||||
case 'h': usage(argv[0],1);
|
||||
@ -107,41 +99,11 @@ int main(int argc, char **argv) {
|
||||
/***********************/
|
||||
|
||||
/* sectors: 2->32 (limited by 4-byte bitfields) */
|
||||
if ((num_sectors<2) || (num_sectors>32)) {
|
||||
printf("Number of sectors must be >2 and <=32\n\n");
|
||||
if ((num_blocks<6) || (num_blocks>65536)) {
|
||||
printf("Number of blocks must be >2 and <65536\n\n");
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* tracks 18-50 ->(sector_size-0x38)/4 */
|
||||
/* limited by VTOC room for freespace bitmap (which is $38 to $ff) */
|
||||
/* VOTC is always on track 17 so we need at least that many */
|
||||
/* though could double if we used the unused sector fields */
|
||||
if ((num_tracks<vtoc_track) || (num_tracks>(sector_size-0x38)/4)) {
|
||||
printf("Number of tracks must be >%d and <=%i\n\n",
|
||||
vtoc_track,(sector_size-0x38)/4);
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* sector_size 256->65536 (or 512 based on one byte t/s size field?) */
|
||||
if ((sector_size<256)||(sector_size>65536)) {
|
||||
printf("Block size must be >=256 and <65536\n\n");
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* allocate space for buffers */
|
||||
vtoc_buffer=calloc(1,sizeof(char)*sector_size);
|
||||
if (vtoc_buffer==NULL) {
|
||||
fprintf(stderr,"Error allocating memory!\n");
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
sector_buffer=calloc(1,sizeof(char)*sector_size);
|
||||
if (sector_buffer==NULL) {
|
||||
fprintf(stderr,"Error allocating memory!\n");
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
|
||||
/* Open device */
|
||||
fd=open(device,O_RDWR|O_CREAT,0666);
|
||||
if (fd<0) {
|
||||
@ -150,205 +112,129 @@ int main(int argc, char **argv) {
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* zero out file */
|
||||
for(i=0;i<num_tracks*num_sectors;i++) {
|
||||
result=write(fd,vtoc_buffer,sector_size);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Calculating Paramaters */
|
||||
/**************************/
|
||||
|
||||
if (volume_number>255) {
|
||||
printf("Warning! Truncating volume number %d to %d\n",
|
||||
volume_number,volume_number&0xff);
|
||||
volume_number&=0xff;
|
||||
}
|
||||
|
||||
if (catalog_track>num_tracks) {
|
||||
printf("Warning! Catalog track too high! Adjusting...\n");
|
||||
catalog_track=(num_tracks/2)+1;
|
||||
}
|
||||
|
||||
if (vtoc_track>num_tracks) {
|
||||
printf("Warning! VTOC track too high! Adjusting...\n");
|
||||
vtoc_track=(num_tracks/2)+1;
|
||||
}
|
||||
|
||||
if (vtoc_track!=17) {
|
||||
printf("Warning! VTOC track is %d, not 17, so unpatched DOS won't be able to find it!\n",
|
||||
vtoc_track);
|
||||
}
|
||||
|
||||
max_ts_pairs=((sector_size-0xc)/2);
|
||||
if (max_ts_pairs>255) {
|
||||
printf("Warning! Truncating max_ts pairs to 255\n");
|
||||
max_ts_pairs=255;
|
||||
}
|
||||
|
||||
catalog_sectors=max_files/7;
|
||||
if (max_files%7) catalog_sectors++;
|
||||
if (catalog_sectors>num_sectors-1) {
|
||||
printf("Warning! num_files leads to too many sectors %d, max is %d\n",catalog_sectors,num_sectors-1);
|
||||
catalog_sectors=num_sectors-1;
|
||||
}
|
||||
|
||||
/***************/
|
||||
/* Create VTOC */
|
||||
/***************/
|
||||
|
||||
/* fake dos 3.3 */
|
||||
vtoc_buffer[VTOC_DOS_RELEASE]=0x3;
|
||||
|
||||
/* 1st Catalog typically at 0x11/0xf */
|
||||
vtoc_buffer[VTOC_CATALOG_T]=catalog_track;
|
||||
vtoc_buffer[VTOC_CATALOG_S]=num_sectors-1;
|
||||
|
||||
/* typically volume is 254 */
|
||||
vtoc_buffer[VTOC_DISK_VOLUME]=volume_number;
|
||||
|
||||
/* Number of T/S pairs fitting */
|
||||
/* in a T/S list sector */
|
||||
/* Note, overflows if sector_size>524 */
|
||||
vtoc_buffer[VTOC_MAX_TS_PAIRS]=max_ts_pairs;
|
||||
|
||||
/* last track space was allocated on */
|
||||
/* so filesystem can try to do things in order */
|
||||
/* also start at catalog track and work our way outward */
|
||||
vtoc_buffer[VTOC_LAST_ALLOC_T]=catalog_track+1;
|
||||
vtoc_buffer[VTOC_ALLOC_DIRECT]=1;
|
||||
|
||||
vtoc_buffer[VTOC_NUM_TRACKS]=num_tracks;
|
||||
vtoc_buffer[VTOC_S_PER_TRACK]=num_sectors;
|
||||
vtoc_buffer[VTOC_BYTES_PER_SL]=sector_size&0xff;
|
||||
vtoc_buffer[VTOC_BYTES_PER_SH]=(sector_size>>8)&0xff;
|
||||
|
||||
/* Set sector bitmap so whole disk is free */
|
||||
for(i=VTOC_FREE_BITMAPS;i<sector_size;i+=4) {
|
||||
vtoc_buffer[i]=0xff;
|
||||
vtoc_buffer[i+1]=0xff;
|
||||
if (num_sectors>16) {
|
||||
vtoc_buffer[i+2]=0xff;
|
||||
vtoc_buffer[i+3]=0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copy over OS from elsewhere, if desired */
|
||||
if (copy_dos) {
|
||||
dos_fd=open(dos_src,O_RDONLY);
|
||||
if (fd<0) {
|
||||
fprintf(stderr,"Error opening %s\n",dos_src);
|
||||
goto end_of_program;
|
||||
}
|
||||
lseek(fd,0,SEEK_SET);
|
||||
/* copy first 3 sectors */
|
||||
for(i=0;i<3*(num_sectors);i++) {
|
||||
result=read(dos_fd,vtoc_buffer,sector_size);
|
||||
result=write(fd,vtoc_buffer,sector_size);
|
||||
}
|
||||
close(dos_fd);
|
||||
|
||||
/* Set boot filename */
|
||||
|
||||
/* Track 1 sector 9 */
|
||||
lseek(fd,((1*num_sectors)+9)*sector_size,SEEK_SET);
|
||||
result=read(fd,vtoc_buffer,sector_size);
|
||||
|
||||
/* filename begins at offset 75 */
|
||||
for(i=0;i<30;i++) {
|
||||
vtoc_buffer[0x75+i]=boot_filename[i]|0x80;
|
||||
}
|
||||
lseek(fd,((1*num_sectors)+9)*sector_size,SEEK_SET);
|
||||
result=write(fd,vtoc_buffer,sector_size);
|
||||
|
||||
/* if copying dos reserve tracks 1 and 2 as well */
|
||||
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+4]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+5]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+6]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+7]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+8]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+9]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+10]=0x00;
|
||||
vtoc_buffer[VTOC_FREE_BITMAPS+11]=0x00;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* reserve track 0 */
|
||||
/* No user data can be stored here as track=0 is used */
|
||||
/* as a special-case end of file indicator */
|
||||
for(i=0;i<num_sectors;i++) {
|
||||
dos33_vtoc_reserve_sector(vtoc_buffer, 0, i);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* reserve the VTOC */
|
||||
/********************/
|
||||
dos33_vtoc_reserve_sector(vtoc_buffer, vtoc_track, 0);
|
||||
|
||||
/*****************/
|
||||
/* Setup Catalog */
|
||||
/* init voldir */
|
||||
/*****************/
|
||||
|
||||
/* clear buffer */
|
||||
memset(sector_buffer,0,sector_size);
|
||||
memset(&voldir,0,sizeof(struct voldir_t));
|
||||
|
||||
/* Set catalog next pointers */
|
||||
for(i=0;i<catalog_sectors;i++) {
|
||||
/* point to next */
|
||||
/* for first sector_size-1 walk backwards from T17S15 */
|
||||
/* if more, allocate room on disk??? */
|
||||
/* Max on 140k disk is 280 or so */
|
||||
voldir.fd=fd;
|
||||
voldir.interleave=interleave;
|
||||
voldir.image_offset=0;
|
||||
voldir.storage_type=PRODOS_FILE_VOLUME_HDR;
|
||||
voldir.name_length=volname_len;
|
||||
memcpy(voldir.volume_name,volname,volname_len);
|
||||
voldir.total_blocks=num_blocks;
|
||||
voldir.version=0;
|
||||
voldir.min_version=0;
|
||||
voldir.access=0xc3; // FIXME
|
||||
voldir.entry_length=0x27;
|
||||
voldir.entries_per_block=13;
|
||||
|
||||
current_sector=num_sectors-i-1;
|
||||
voldir.bit_map_pointer=6;
|
||||
|
||||
if (i==catalog_sectors-1) {
|
||||
/* last one, pointer is to 0,0 */
|
||||
sector_buffer[1]=0;
|
||||
sector_buffer[2]=0;
|
||||
voldir.creation_time=0;
|
||||
|
||||
voldir.file_count=0;
|
||||
|
||||
voldir.next_block=3;
|
||||
|
||||
/******************/
|
||||
/* clear out data */
|
||||
/******************/
|
||||
|
||||
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||
|
||||
/* create image */
|
||||
for(i=0;i<num_blocks;i++) {
|
||||
result=prodos_write_block(&voldir,data_buffer,i);
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error writing!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************/
|
||||
/* create the voldirs */
|
||||
/*********************************/
|
||||
for(i=0;i<num_voldirs;i++) {
|
||||
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||
/* prev */
|
||||
if (i>0) {
|
||||
data_buffer[0]=(PRODOS_VOLDIR_KEY_BLOCK+i-1)&0xff;
|
||||
data_buffer[1]=(PRODOS_VOLDIR_KEY_BLOCK+i-1)>>8;
|
||||
}
|
||||
/* next */
|
||||
if (i<num_voldirs-1) {
|
||||
data_buffer[2]=(PRODOS_VOLDIR_KEY_BLOCK+i+1)&0xff;
|
||||
data_buffer[3]=(PRODOS_VOLDIR_KEY_BLOCK+i+1)>>8;
|
||||
}
|
||||
result=prodos_write_block(&voldir,data_buffer,i+PRODOS_VOLDIR_KEY_BLOCK);
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/* create the bitmaps */
|
||||
/*********************************/
|
||||
num_bitmaps=num_blocks/8;
|
||||
num_bitmap_blocks=1+((num_bitmaps-1)/512);
|
||||
|
||||
for(i=0;i<num_bitmap_blocks;i++) {
|
||||
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||
|
||||
if (i*512*8>num_blocks) {
|
||||
ones_to_write=512;
|
||||
}
|
||||
else {
|
||||
printf("Writing $%02X,$%02X=%d,%d\n",
|
||||
catalog_track,current_sector,
|
||||
catalog_track,current_sector-1);
|
||||
sector_buffer[1]=catalog_track;
|
||||
sector_buffer[2]=current_sector-1;
|
||||
ones_to_write=num_blocks%(512*8);
|
||||
}
|
||||
|
||||
/* reserve */
|
||||
dos33_vtoc_reserve_sector(vtoc_buffer,
|
||||
catalog_track, current_sector);
|
||||
if (debug) printf("Writing %d ones\n",ones_to_write);
|
||||
|
||||
lseek(fd,((catalog_track*num_sectors)+current_sector)*
|
||||
sector_size,SEEK_SET);
|
||||
result=write(fd,sector_buffer,sector_size);
|
||||
if (result!=sector_size) {
|
||||
fprintf(stderr,"Error writing catalog sector %d! (%s)\n",
|
||||
current_sector,strerror(errno));
|
||||
for(j=0;j<ones_to_write/8;j++) {
|
||||
data_buffer[j]=0xff;
|
||||
}
|
||||
if (ones_to_write%8) {
|
||||
data_buffer[j]=ones_lookup[ones_to_write%8];
|
||||
}
|
||||
|
||||
result=prodos_write_block(&voldir,data_buffer,
|
||||
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i);
|
||||
|
||||
if (debug) printf("Wrote bitmap to block $%X\n",
|
||||
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i);
|
||||
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error writing!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Write out VTOC to disk */
|
||||
/**************************/
|
||||
lseek(fd,((vtoc_track*num_sectors)+0)*sector_size,SEEK_SET);
|
||||
/*********************************/
|
||||
/* reserve all of the used space */
|
||||
/*********************************/
|
||||
|
||||
result=write(fd,vtoc_buffer,sector_size);
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error writing VTOC (%s)!\n",strerror(errno));
|
||||
prodos_voldir_reserve_block(&voldir,0); // boot sector
|
||||
prodos_voldir_reserve_block(&voldir,1); // SOS boot sector
|
||||
for(i=0;i<num_voldirs;i++) {
|
||||
prodos_voldir_reserve_block(&voldir,
|
||||
PRODOS_VOLDIR_KEY_BLOCK+i); // 2..5
|
||||
}
|
||||
for(i=0;i<num_bitmap_blocks;i++) {
|
||||
prodos_voldir_reserve_block(&voldir,
|
||||
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i); // 6
|
||||
}
|
||||
|
||||
#endif
|
||||
/*********************************/
|
||||
/* write out voldir */
|
||||
/*********************************/
|
||||
prodos_sync_voldir(&voldir);
|
||||
|
||||
close(fd);
|
||||
|
||||
end_of_program:
|
||||
if (vtoc_buffer) free(vtoc_buffer);
|
||||
if (sector_buffer) free(sector_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,60 +14,6 @@
|
||||
static int ignore_errors=0;
|
||||
int debug=1;
|
||||
|
||||
/* Read volume directory into a buffer */
|
||||
static int prodos_read_voldir(int fd, struct voldir_t *voldir,
|
||||
int interleave, int image_offset) {
|
||||
|
||||
int result;
|
||||
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||
|
||||
voldir->interleave=interleave;
|
||||
voldir->image_offset=image_offset;
|
||||
|
||||
/* read in VOLDIR KEY Block*/
|
||||
voldir->fd=fd;
|
||||
result=prodos_read_block(voldir,voldir_buffer,PRODOS_VOLDIR_KEY_BLOCK);
|
||||
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error reading VOLDIR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
voldir->fd=fd;
|
||||
|
||||
voldir->storage_type=(voldir_buffer[0x4]>>4)&0xf;
|
||||
voldir->name_length=(voldir_buffer[0x4]&0xf);
|
||||
if (voldir->storage_type!=0xf) {
|
||||
fprintf(stderr,"ERROR! Expected storage type F\n");
|
||||
}
|
||||
|
||||
memcpy(voldir->volume_name,&voldir_buffer[0x5],voldir->name_length);
|
||||
voldir->volume_name[voldir->name_length]=0;
|
||||
|
||||
voldir->creation_time=(voldir_buffer[0x1c]<<16)|
|
||||
(voldir_buffer[0x1d]<<24)|
|
||||
(voldir_buffer[0x1e]<<0)|
|
||||
(voldir_buffer[0x1f]<<8);
|
||||
|
||||
voldir->version=voldir_buffer[0x20];
|
||||
voldir->min_version=voldir_buffer[0x21];
|
||||
voldir->access=voldir_buffer[0x22];
|
||||
voldir->entry_length=voldir_buffer[0x23];
|
||||
|
||||
if (voldir->entry_length!=PRODOS_FILE_DESC_LEN) {
|
||||
printf("Error! Unexpected desc len %d\n",
|
||||
voldir->entry_length);
|
||||
}
|
||||
|
||||
voldir->entries_per_block=voldir_buffer[0x24];
|
||||
voldir->file_count=voldir_buffer[0x25]|(voldir_buffer[0x26]<<8);
|
||||
voldir->bit_map_pointer=voldir_buffer[0x27]|(voldir_buffer[0x28]<<8);
|
||||
voldir->total_blocks=voldir_buffer[0x29]|(voldir_buffer[0x2A]<<8);
|
||||
voldir->next_block=voldir_buffer[0x2]|(voldir_buffer[0x3]<<8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Given filename, return voldir/offset */
|
||||
static int prodos_lookup_file(struct voldir_t *voldir,
|
||||
@ -480,6 +426,10 @@ static int prodos_add_file(struct voldir_t *voldir,
|
||||
/* write back existing voldir entry */
|
||||
result=prodos_write_block(voldir,data_buffer,inode>>8);
|
||||
|
||||
/* update file count */
|
||||
voldir->file_count++;
|
||||
prodos_sync_voldir(voldir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -900,66 +850,6 @@ static int truncate_filename(char *out, char *in) {
|
||||
return truncated;
|
||||
}
|
||||
|
||||
static int prodos_sync_voldir(struct voldir_t *voldir) {
|
||||
|
||||
unsigned char newvoldir[PRODOS_BYTES_PER_BLOCK];
|
||||
|
||||
memset(newvoldir,0,PRODOS_BYTES_PER_BLOCK);
|
||||
|
||||
newvoldir[0x4]=(voldir->storage_type<<4)|(voldir->name_length&0xf);
|
||||
memcpy(&newvoldir[0x5],voldir->volume_name,voldir->name_length);
|
||||
|
||||
/* FIXME: probably endianess issues */
|
||||
|
||||
newvoldir[0x1c]=(voldir->creation_time>>16)&0xff;
|
||||
newvoldir[0x1d]=(voldir->creation_time>>24)&0xff;
|
||||
newvoldir[0x1e]=(voldir->creation_time>>0)&0xff;
|
||||
newvoldir[0x1f]=(voldir->creation_time>>8)&0xff;
|
||||
|
||||
newvoldir[0x20]=voldir->version;
|
||||
newvoldir[0x21]=voldir->min_version;
|
||||
newvoldir[0x22]=voldir->access;
|
||||
newvoldir[0x23]=voldir->entry_length;
|
||||
|
||||
newvoldir[0x24]=voldir->entries_per_block;
|
||||
|
||||
newvoldir[0x25]=voldir->file_count&0xff;
|
||||
newvoldir[0x26]=(voldir->file_count>>8)&0xff;
|
||||
|
||||
newvoldir[0x27]=voldir->bit_map_pointer&0xff;
|
||||
newvoldir[0x28]=(voldir->bit_map_pointer>>8)&0xff;
|
||||
|
||||
newvoldir[0x29]=voldir->total_blocks&0xff;
|
||||
newvoldir[0x2A]=(voldir->total_blocks>>8)&0xff;
|
||||
|
||||
newvoldir[0x2]=voldir->next_block&0xff;
|
||||
newvoldir[0x3]=(voldir->next_block>>8)&0xff;
|
||||
|
||||
prodos_write_block(voldir,newvoldir,PRODOS_VOLDIR_KEY_BLOCK);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int change_volume_name(struct voldir_t *voldir, char *volname) {
|
||||
|
||||
int volname_len;
|
||||
|
||||
volname_len=strlen(volname);
|
||||
if (volname_len>15) {
|
||||
printf("Warning! Volume name %s is too long, truncating\n",
|
||||
volname);
|
||||
volname_len=15;
|
||||
}
|
||||
|
||||
memcpy(voldir->volume_name,volname,15);
|
||||
voldir->name_length=volname_len;
|
||||
|
||||
prodos_sync_voldir(voldir);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
@ -1387,7 +1277,7 @@ int main(int argc, char **argv) {
|
||||
goto exit_and_close;
|
||||
}
|
||||
|
||||
change_volume_name(&voldir,argv[optind]);
|
||||
prodos_change_volume_name(&voldir,argv[optind]);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
/* For now hard-coded */
|
||||
/* Could be made dynamic if we want to be useful */
|
||||
/* On dos3.2 disks, or larger filesystems */
|
||||
#define TRACKS_PER_DISK 0x23
|
||||
#define BLOCKS_PER_TRACK 0x8
|
||||
|
||||
#define PRODOS_BYTES_PER_BLOCK 0x200
|
||||
#define PRODOS_VOLNAME_LEN 15
|
||||
#define PRODOS_FILENAME_LEN 15
|
||||
|
||||
#define PRODOS_INTERLEAVE_PRODOS 0x0
|
||||
#define PRODOS_INTERLEAVE_DOS33 0x1
|
||||
@ -86,3 +87,9 @@ int prodos_showfree(struct voldir_t *voldir, int fd);
|
||||
/* prodos_read.c */
|
||||
int prodos_read_block(struct voldir_t *voldir,unsigned char *block, int blocknum);
|
||||
int prodos_write_block(struct voldir_t *voldir,unsigned char *block, int blocknum);
|
||||
|
||||
/* prodos_voldir.c */
|
||||
int prodos_sync_voldir(struct voldir_t *voldir);
|
||||
int prodos_change_volume_name(struct voldir_t *voldir, char *volname);
|
||||
int prodos_read_voldir(int fd, struct voldir_t *voldir,
|
||||
int interleave, int image_offset);
|
||||
|
131
utils/prodos-utils/prodos_voldir.c
Normal file
131
utils/prodos-utils/prodos_voldir.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* exit() */
|
||||
#include <string.h> /* strncpy() */
|
||||
#include <sys/stat.h> /* struct stat */
|
||||
#include <fcntl.h> /* O_RDONLY */
|
||||
#include <unistd.h> /* lseek() */
|
||||
#include <ctype.h> /* toupper() */
|
||||
#include <errno.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
extern int debug;
|
||||
|
||||
/* Read volume directory into a buffer */
|
||||
int prodos_read_voldir(int fd, struct voldir_t *voldir,
|
||||
int interleave, int image_offset) {
|
||||
|
||||
int result;
|
||||
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||
|
||||
voldir->interleave=interleave;
|
||||
voldir->image_offset=image_offset;
|
||||
|
||||
/* read in VOLDIR KEY Block*/
|
||||
voldir->fd=fd;
|
||||
result=prodos_read_block(voldir,voldir_buffer,PRODOS_VOLDIR_KEY_BLOCK);
|
||||
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error reading VOLDIR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
voldir->fd=fd;
|
||||
|
||||
voldir->storage_type=(voldir_buffer[0x4]>>4)&0xf;
|
||||
voldir->name_length=(voldir_buffer[0x4]&0xf);
|
||||
if (voldir->storage_type!=0xf) {
|
||||
fprintf(stderr,"ERROR! Expected storage type F\n");
|
||||
}
|
||||
|
||||
memcpy(voldir->volume_name,&voldir_buffer[0x5],voldir->name_length);
|
||||
voldir->volume_name[voldir->name_length]=0;
|
||||
|
||||
voldir->creation_time=(voldir_buffer[0x1c]<<16)|
|
||||
(voldir_buffer[0x1d]<<24)|
|
||||
(voldir_buffer[0x1e]<<0)|
|
||||
(voldir_buffer[0x1f]<<8);
|
||||
|
||||
voldir->version=voldir_buffer[0x20];
|
||||
voldir->min_version=voldir_buffer[0x21];
|
||||
voldir->access=voldir_buffer[0x22];
|
||||
voldir->entry_length=voldir_buffer[0x23];
|
||||
|
||||
if (voldir->entry_length!=PRODOS_FILE_DESC_LEN) {
|
||||
printf("Error! Unexpected desc len %d\n",
|
||||
voldir->entry_length);
|
||||
}
|
||||
|
||||
voldir->entries_per_block=voldir_buffer[0x24];
|
||||
voldir->file_count=voldir_buffer[0x25]|(voldir_buffer[0x26]<<8);
|
||||
voldir->bit_map_pointer=voldir_buffer[0x27]|(voldir_buffer[0x28]<<8);
|
||||
voldir->total_blocks=voldir_buffer[0x29]|(voldir_buffer[0x2A]<<8);
|
||||
voldir->next_block=voldir_buffer[0x2]|(voldir_buffer[0x3]<<8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int prodos_sync_voldir(struct voldir_t *voldir) {
|
||||
|
||||
unsigned char newvoldir[PRODOS_BYTES_PER_BLOCK];
|
||||
|
||||
memset(newvoldir,0,PRODOS_BYTES_PER_BLOCK);
|
||||
|
||||
newvoldir[0x4]=(voldir->storage_type<<4)|(voldir->name_length&0xf);
|
||||
memcpy(&newvoldir[0x5],voldir->volume_name,voldir->name_length);
|
||||
|
||||
/* FIXME: probably endianess issues */
|
||||
|
||||
newvoldir[0x1c]=(voldir->creation_time>>16)&0xff;
|
||||
newvoldir[0x1d]=(voldir->creation_time>>24)&0xff;
|
||||
newvoldir[0x1e]=(voldir->creation_time>>0)&0xff;
|
||||
newvoldir[0x1f]=(voldir->creation_time>>8)&0xff;
|
||||
|
||||
newvoldir[0x20]=voldir->version;
|
||||
newvoldir[0x21]=voldir->min_version;
|
||||
newvoldir[0x22]=voldir->access;
|
||||
newvoldir[0x23]=voldir->entry_length;
|
||||
|
||||
newvoldir[0x24]=voldir->entries_per_block;
|
||||
|
||||
newvoldir[0x25]=voldir->file_count&0xff;
|
||||
newvoldir[0x26]=(voldir->file_count>>8)&0xff;
|
||||
|
||||
newvoldir[0x27]=voldir->bit_map_pointer&0xff;
|
||||
newvoldir[0x28]=(voldir->bit_map_pointer>>8)&0xff;
|
||||
|
||||
newvoldir[0x29]=voldir->total_blocks&0xff;
|
||||
newvoldir[0x2A]=(voldir->total_blocks>>8)&0xff;
|
||||
|
||||
newvoldir[0x2]=voldir->next_block&0xff;
|
||||
newvoldir[0x3]=(voldir->next_block>>8)&0xff;
|
||||
|
||||
prodos_write_block(voldir,newvoldir,PRODOS_VOLDIR_KEY_BLOCK);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int prodos_change_volume_name(struct voldir_t *voldir, char *volname) {
|
||||
|
||||
int volname_len;
|
||||
|
||||
volname_len=strlen(volname);
|
||||
if (volname_len>15) {
|
||||
printf("Warning! Volume name %s is too long, truncating\n",
|
||||
volname);
|
||||
volname_len=15;
|
||||
}
|
||||
|
||||
memcpy(voldir->volume_name,volname,15);
|
||||
voldir->name_length=volname_len;
|
||||
|
||||
prodos_sync_voldir(voldir);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user