mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-09-27 11:55:20 +00:00
prodos: save sort of working
not all the attributes are being set, but a sapling survived a save/load round trip
This commit is contained in:
parent
322ba44833
commit
9047bce044
@ -114,6 +114,50 @@ static int prodos_lookup_file(struct voldir_t *voldir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Given filename, return voldir/offset */
|
||||||
|
/* FIXME: allocate new voldir block if all full */
|
||||||
|
static int prodos_allocate_directory_entry(struct voldir_t *voldir) {
|
||||||
|
|
||||||
|
int voldir_block,voldir_offset;
|
||||||
|
struct file_entry_t file_entry;
|
||||||
|
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
|
int result,file;
|
||||||
|
|
||||||
|
voldir_block=PRODOS_VOLDIR_KEY_BLOCK;
|
||||||
|
voldir_offset=1; /* skip the header */
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
/* Read in Block */
|
||||||
|
result=prodos_read_block(voldir,
|
||||||
|
voldir_buffer,voldir_block);
|
||||||
|
if (result<0) {
|
||||||
|
fprintf(stderr,"Error on I/O\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(file=voldir_offset;
|
||||||
|
file<voldir->entries_per_block;file++) {
|
||||||
|
|
||||||
|
prodos_populate_filedesc(
|
||||||
|
voldir_buffer+4+file*PRODOS_FILE_DESC_LEN,
|
||||||
|
&file_entry);
|
||||||
|
|
||||||
|
if (file_entry.storage_type==PRODOS_FILE_DELETED) {
|
||||||
|
return (voldir_block<<8)|file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
voldir_offset=0;
|
||||||
|
voldir_block=voldir_buffer[2]|(voldir_buffer[3]<<8);
|
||||||
|
if (voldir_block==0) break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Checks if "filename" exists */
|
/* Checks if "filename" exists */
|
||||||
/* returns file type */
|
/* returns file type */
|
||||||
@ -150,41 +194,72 @@ static int prodos_free_block(struct voldir_t *voldir,int block) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prodos_allocate_sector(int fd, struct voldir_t *voldir) {
|
static int prodos_allocate_block(struct voldir_t *voldir) {
|
||||||
|
|
||||||
#if 0
|
int found_block=0;
|
||||||
|
|
||||||
int found_track=0,found_sector=0;
|
/* Find an empty block */
|
||||||
int result;
|
found_block=prodos_voldir_find_free_block(voldir);
|
||||||
|
if (debug) printf("Found free block %x\n",found_block);
|
||||||
|
|
||||||
/* Find an empty sector */
|
if (found_block<0) {
|
||||||
result=prodos_voldir_find_free_sector(voldir,&found_track,&found_sector);
|
|
||||||
|
|
||||||
if (result<0) {
|
|
||||||
fprintf(stderr,"ERROR: prodos_allocate_sector: Disk full!\n");
|
fprintf(stderr,"ERROR: prodos_allocate_sector: Disk full!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prodos_voldir_reserve_block(voldir,found_block);
|
||||||
|
|
||||||
/* store new track/direction info */
|
return found_block;
|
||||||
voldir[VTOC_LAST_ALLOC_T]=found_track;
|
|
||||||
|
|
||||||
// if (found_track>PRODOS_VOLDIR_TRACK) vtoc[VTOC_ALLOC_DIRECT]=1;
|
}
|
||||||
// else vtoc[VTOC_ALLOC_DIRECT]=-1;
|
|
||||||
|
|
||||||
/* Seek to VTOC */
|
|
||||||
lseek(fd,DISK_OFFSET(PRODOS_VOLDIR_TRACK,PRODOS_VOLDIR_BLOCK),SEEK_SET);
|
|
||||||
|
|
||||||
/* Write out VTOC */
|
static int prodos_writeout_filedesc(struct voldir_t *voldir,
|
||||||
result=write(fd,voldir,PRODOS_BYTES_PER_BLOCK);
|
struct file_entry_t *file_entry,
|
||||||
|
unsigned char *dest) {
|
||||||
|
|
||||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
/* clear it out */
|
||||||
|
memset(dest,0,PRODOS_FILE_DESC_LEN);
|
||||||
|
|
||||||
|
dest[0x00]=(file_entry->storage_type<<4)|(file_entry->name_length&0xf);
|
||||||
|
memcpy(&dest[0x01],&file_entry->file_name[0],file_entry->name_length);
|
||||||
|
|
||||||
|
dest[0x10]=file_entry->file_type;
|
||||||
|
|
||||||
|
dest[0x11]=file_entry->key_pointer&0xff;
|
||||||
|
dest[0x12]=(file_entry->key_pointer>>8)&0xff;
|
||||||
|
|
||||||
|
dest[0x13]=file_entry->blocks_used&0xff;
|
||||||
|
dest[0x14]=(file_entry->blocks_used>>8)&0xff;
|
||||||
|
|
||||||
|
dest[0x15]=file_entry->eof&0xff;
|
||||||
|
dest[0x16]=(file_entry->eof>>8)&0xff;
|
||||||
|
dest[0x17]=(file_entry->eof>>16)&0xff;
|
||||||
|
|
||||||
|
dest[0x18]=(file_entry->creation_time>>16)&0xff;
|
||||||
|
dest[0x19]=(file_entry->creation_time>>24)&0xff;
|
||||||
|
dest[0x1a]=(file_entry->creation_time>>0)&0xff;
|
||||||
|
dest[0x1b]=(file_entry->creation_time>>8)&0xff;
|
||||||
|
|
||||||
|
dest[0x1c]=file_entry->version;
|
||||||
|
dest[0x1d]=file_entry->min_version;
|
||||||
|
dest[0x1e]=file_entry->access;
|
||||||
|
|
||||||
|
dest[0x1f]=file_entry->aux_type&0xff;
|
||||||
|
dest[0x20]=(file_entry->aux_type>>8)&0xff;
|
||||||
|
|
||||||
|
dest[0x21]=(file_entry->last_mod>>16)&0xff;
|
||||||
|
dest[0x22]=(file_entry->last_mod>>24)&0xff;
|
||||||
|
dest[0x23]=(file_entry->last_mod>>0)&0xff;
|
||||||
|
dest[0x24]=(file_entry->last_mod>>8)&0xff;
|
||||||
|
|
||||||
|
dest[0x25]=file_entry->header_pointer&0xff;
|
||||||
|
dest[0x26]=(file_entry->header_pointer>>8)&0xff;
|
||||||
|
|
||||||
return ((found_track<<8)+found_sector);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define ERROR_MYSTERY 1
|
#define ERROR_MYSTERY 1
|
||||||
#define ERROR_INVALID_FILENAME 2
|
#define ERROR_INVALID_FILENAME 2
|
||||||
#define ERROR_FILE_NOT_FOUND 3
|
#define ERROR_FILE_NOT_FOUND 3
|
||||||
@ -203,16 +278,15 @@ static int prodos_add_file(struct voldir_t *voldir,
|
|||||||
|
|
||||||
|
|
||||||
int free_blocks,file_size,needed_blocks,total_blocks,file_type;
|
int free_blocks,file_size,needed_blocks,total_blocks,file_type;
|
||||||
|
int block,i,j,needed_limit;
|
||||||
struct stat file_info;
|
struct stat file_info;
|
||||||
int size_in_sectors=0;
|
|
||||||
int initial_ts_list=0,ts_list=0,i,data_ts,x,bytes_read=0,old_ts_list;
|
|
||||||
int catalog_track,catalog_sector,sectors_used=0;
|
|
||||||
int input_fd;
|
int input_fd;
|
||||||
int result;
|
int result;
|
||||||
int first_write=1;
|
unsigned char key_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
unsigned char ts_buffer[PRODOS_BYTES_PER_BLOCK];
|
unsigned char index_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
unsigned char catalog_buffer[PRODOS_BYTES_PER_BLOCK];
|
|
||||||
unsigned char data_buffer[PRODOS_BYTES_PER_BLOCK];
|
unsigned char data_buffer[PRODOS_BYTES_PER_BLOCK];
|
||||||
|
int key_block,index,inode;
|
||||||
|
struct file_entry_t file;
|
||||||
|
|
||||||
/* check for valid filename */
|
/* check for valid filename */
|
||||||
|
|
||||||
@ -297,195 +371,123 @@ static int prodos_add_file(struct voldir_t *voldir,
|
|||||||
return ERROR_IMAGE_NOT_FOUND;
|
return ERROR_IMAGE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (file_type==PRODOS_FILE_SEEDLING) {
|
||||||
i=0;
|
block=prodos_allocate_block(voldir);
|
||||||
while (i<size_in_sectors) {
|
key_block=block;
|
||||||
|
|
||||||
/* Create new T/S list if necessary */
|
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
if (i%TSL_MAX_NUMBER==0) {
|
result=read(input_fd,data_buffer,PRODOS_BYTES_PER_BLOCK);
|
||||||
old_ts_list=ts_list;
|
if (result<0) {
|
||||||
|
fprintf(stderr,"Error reading\n");
|
||||||
/* allocate a sector for the new list */
|
return -ERROR_MYSTERY;
|
||||||
ts_list=prodos_allocate_sector(fd,voldir);
|
|
||||||
sectors_used++;
|
|
||||||
if (ts_list<0) return -1;
|
|
||||||
|
|
||||||
/* clear the t/s sector */
|
|
||||||
memset(ts_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
|
||||||
result=write(fd,ts_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
if (i==0) {
|
|
||||||
initial_ts_list=ts_list;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* we aren't the first t/s list so do special stuff */
|
|
||||||
|
|
||||||
/* load in the old t/s list */
|
|
||||||
lseek(fd,
|
|
||||||
DISK_OFFSET(get_high_byte(old_ts_list),
|
|
||||||
get_low_byte(old_ts_list)),
|
|
||||||
SEEK_SET);
|
|
||||||
|
|
||||||
result=read(fd,ts_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
/* point from old ts list to new one we just made */
|
|
||||||
ts_buffer[TSL_NEXT_TRACK]=get_high_byte(ts_list);
|
|
||||||
ts_buffer[TSL_NEXT_SECTOR]=get_low_byte(ts_list);
|
|
||||||
|
|
||||||
/* set offset into file */
|
|
||||||
ts_buffer[TSL_OFFSET_H]=get_high_byte((i-122)*256);
|
|
||||||
ts_buffer[TSL_OFFSET_L]=get_low_byte((i-122)*256);
|
|
||||||
|
|
||||||
/* write out the old t/s list with updated info */
|
|
||||||
lseek(fd,
|
|
||||||
DISK_OFFSET(get_high_byte(old_ts_list),
|
|
||||||
get_low_byte(old_ts_list)),
|
|
||||||
SEEK_SET);
|
|
||||||
|
|
||||||
result=write(fd,ts_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
}
|
}
|
||||||
|
prodos_write_block(voldir,data_buffer,block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a sector */
|
if (file_type==PRODOS_FILE_SAPLING) {
|
||||||
data_ts=prodos_allocate_sector(fd,voldir);
|
/* allocate index */
|
||||||
sectors_used++;
|
index=prodos_allocate_block(voldir);
|
||||||
|
key_block=index;
|
||||||
|
|
||||||
if (data_ts<0) return -1;
|
memset(index_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
|
|
||||||
|
for(i=0;i<needed_blocks;i++) {
|
||||||
|
block=prodos_allocate_block(voldir);
|
||||||
|
|
||||||
|
index_buffer[i]=block&0xff;
|
||||||
|
index_buffer[i+256]=(block>>8)&0xff;
|
||||||
|
|
||||||
/* clear data sector */
|
|
||||||
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
|
|
||||||
/* read from input */
|
result=read(input_fd,data_buffer,PRODOS_BYTES_PER_BLOCK);
|
||||||
if ((first_write) && (file_type==ADD_BINARY)) {
|
if (result<0) {
|
||||||
first_write=0;
|
fprintf(stderr,"Error reading\n");
|
||||||
data_buffer[0]=address&0xff;
|
return -ERROR_MYSTERY;
|
||||||
data_buffer[1]=(address>>8)&0xff;
|
}
|
||||||
data_buffer[2]=(length)&0xff;
|
prodos_write_block(voldir,data_buffer,block);
|
||||||
data_buffer[3]=((length)>>8)&0xff;
|
}
|
||||||
bytes_read=read(input_fd,data_buffer+4,
|
prodos_write_block(voldir,index_buffer,index);
|
||||||
PRODOS_BYTES_PER_BLOCK-4);
|
}
|
||||||
bytes_read+=4;
|
|
||||||
|
|
||||||
|
if (file_type==PRODOS_FILE_TREE) {
|
||||||
|
/* allocate key index */
|
||||||
|
key_block=prodos_allocate_block(voldir);
|
||||||
|
memset(key_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
|
|
||||||
|
for(j=0;j<(1+needed_blocks/256);j++) {
|
||||||
|
index=prodos_allocate_block(voldir);
|
||||||
|
memset(index_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
|
|
||||||
|
key_buffer[j]=index&0xff;
|
||||||
|
key_buffer[j+256]=(index>>8)&0xff;
|
||||||
|
|
||||||
|
if (j==needed_blocks/256) {
|
||||||
|
needed_limit=needed_blocks%256;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bytes_read=read(input_fd,data_buffer,
|
needed_limit=256;
|
||||||
PRODOS_BYTES_PER_BLOCK);
|
|
||||||
}
|
|
||||||
first_write=0;
|
|
||||||
|
|
||||||
if (bytes_read<0) fprintf(stderr,"Error reading bytes!\n");
|
|
||||||
|
|
||||||
/* write to disk image */
|
|
||||||
lseek(fd,DISK_OFFSET((data_ts>>8)&0xff,data_ts&0xff),SEEK_SET);
|
|
||||||
result=write(fd,data_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
printf("Writing %i bytes to %i/%i\n",
|
|
||||||
bytes_read,(data_ts>>8)&0xff,data_ts&0xff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add to T/s table */
|
for(i=0;i<needed_limit;i++) {
|
||||||
|
block=prodos_allocate_block(voldir);
|
||||||
|
|
||||||
/* read in t/s list */
|
index_buffer[i]=block&0xff;
|
||||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
index_buffer[i+256]=(block>>8)&0xff;
|
||||||
result=read(fd,ts_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
/* point to new data sector */
|
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
|
||||||
ts_buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST]=(data_ts>>8)&0xff;
|
|
||||||
ts_buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST+1]=(data_ts&0xff);
|
|
||||||
|
|
||||||
/* write t/s list back out */
|
result=read(input_fd,data_buffer,PRODOS_BYTES_PER_BLOCK);
|
||||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
if (result<0) {
|
||||||
result=write(fd,ts_buffer,PRODOS_BYTES_PER_BLOCK);
|
fprintf(stderr,"Error reading\n");
|
||||||
|
return -ERROR_MYSTERY;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
prodos_write_block(voldir,data_buffer,block);
|
||||||
/* Add new file to Catalog */
|
|
||||||
|
|
||||||
catalog_track=voldir[VTOC_CATALOG_T];
|
|
||||||
catalog_sector=voldir[VTOC_CATALOG_S];
|
|
||||||
|
|
||||||
continue_parsing_catalog:
|
|
||||||
|
|
||||||
/* Read in Catalog Sector */
|
|
||||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
|
||||||
result=read(fd,catalog_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
if (result!=PRODOS_BYTES_PER_BLOCK) {
|
|
||||||
fprintf(stderr,"Catalog: Error, only read %d bytes at $%02X:$%02X (%s)\n",
|
|
||||||
result,catalog_track,catalog_sector,strerror(errno));
|
|
||||||
return ERROR_NO_SPACE;
|
|
||||||
}
|
}
|
||||||
|
prodos_write_block(voldir,index_buffer,index);
|
||||||
/* Find empty directory entry */
|
|
||||||
i=0;
|
|
||||||
while(i<7) {
|
|
||||||
/* for undelete purposes might want to skip 0xff */
|
|
||||||
/* (deleted) files first and only use if no room */
|
|
||||||
|
|
||||||
if ((catalog_buffer[CATALOG_FILE_LIST+
|
|
||||||
(i*CATALOG_ENTRY_SIZE)]==0xff) ||
|
|
||||||
(catalog_buffer[CATALOG_FILE_LIST+
|
|
||||||
(i*CATALOG_ENTRY_SIZE)]==0x00)) {
|
|
||||||
goto got_a_dentry;
|
|
||||||
}
|
}
|
||||||
i++;
|
prodos_write_block(voldir,key_buffer,key_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((catalog_track=0x11) && (catalog_sector==1)) {
|
|
||||||
/* in theory can only have 105 files */
|
|
||||||
/* if full, we have no recourse! */
|
|
||||||
/* can we allocate new catalog sectors */
|
|
||||||
/* and point to them?? */
|
|
||||||
fprintf(stderr,"Error! No more room for files!\n");
|
|
||||||
return ERROR_CATALOG_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
catalog_track=catalog_buffer[CATALOG_NEXT_T];
|
|
||||||
catalog_sector=catalog_buffer[CATALOG_NEXT_S];
|
|
||||||
|
|
||||||
goto continue_parsing_catalog;
|
|
||||||
|
|
||||||
got_a_dentry:
|
|
||||||
// printf("Adding file at entry %i of catalog 0x%x:0x%x\n",
|
|
||||||
// i,catalog_track,catalog_sector);
|
|
||||||
|
|
||||||
/* Point entry to initial t/s list */
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]=(initial_ts_list>>8)&0xff;
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+1]=(initial_ts_list&0xff);
|
|
||||||
/* set file type */
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_TYPE]=
|
|
||||||
prodos_char_to_type(dos_type,0);
|
|
||||||
|
|
||||||
// printf("Pointing T/S to %x/%x\n",(initial_ts_list>>8)&0xff,initial_ts_list&0xff);
|
|
||||||
|
|
||||||
/* copy over filename */
|
|
||||||
for(x=0;x<strlen(apple_filename);x++) {
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_NAME+x]=
|
|
||||||
apple_filename[x]^0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pad out the filename with spaces */
|
|
||||||
for(x=strlen(apple_filename);x<FILE_NAME_SIZE;x++) {
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_NAME+x]=' '^0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill in filesize in sectors */
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_SIZE_L]=
|
|
||||||
sectors_used&0xff;
|
|
||||||
catalog_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_SIZE_H]=
|
|
||||||
(sectors_used>>8)&0xff;
|
|
||||||
|
|
||||||
/* write out catalog sector */
|
|
||||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
|
||||||
result=write(fd,catalog_buffer,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
close(input_fd);
|
close(input_fd);
|
||||||
|
|
||||||
|
/* now that file is on disk, hook up the directory image */
|
||||||
|
|
||||||
|
memset(&file,0,sizeof(struct file_entry_t));
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
file.storage_type=file_type;
|
||||||
|
file.name_length=strlen(apple_filename);
|
||||||
|
memcpy(file.file_name,apple_filename,file.name_length);
|
||||||
|
file.file_type=0;
|
||||||
|
file.key_pointer=key_block;
|
||||||
|
file.blocks_used=total_blocks; /* includes index blocks */
|
||||||
|
file.eof=file_size;
|
||||||
|
file.creation_time=0;
|
||||||
|
file.version=0;
|
||||||
|
file.min_version=0;
|
||||||
|
file.access=0;
|
||||||
|
file.aux_type=0;
|
||||||
|
file.last_mod=0;
|
||||||
|
file.header_pointer=PRODOS_VOLDIR_KEY_BLOCK;
|
||||||
|
|
||||||
|
|
||||||
|
inode=prodos_allocate_directory_entry(voldir);
|
||||||
|
if (inode<0) {
|
||||||
|
return inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read in existing voldir entry */
|
||||||
|
result=prodos_read_block(voldir,data_buffer,inode>>8);
|
||||||
|
|
||||||
|
/* copy in new data */
|
||||||
|
prodos_writeout_filedesc(voldir,&file,
|
||||||
|
data_buffer+4+(inode&0xff)*PRODOS_FILE_DESC_LEN);
|
||||||
|
|
||||||
|
/* write back existing voldir entry */
|
||||||
|
result=prodos_write_block(voldir,data_buffer,inode>>8);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,9 +679,9 @@ static int prodos_load_file(struct voldir_t *voldir,
|
|||||||
|
|
||||||
|
|
||||||
/* rename a file. fts=entry/track/sector */
|
/* rename a file. fts=entry/track/sector */
|
||||||
/* FIXME: can we rename a locked file? */
|
|
||||||
/* FIXME: validate the new filename is valid */
|
/* FIXME: validate the new filename is valid */
|
||||||
static int prodos_rename_file(int fd,char *old_name,char *new_name) {
|
static int prodos_rename_file(struct voldir_t *voldir,
|
||||||
|
char *old_name,char *new_name) {
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int catalog_file,catalog_track,catalog_sector;
|
int catalog_file,catalog_track,catalog_sector;
|
||||||
@ -1369,7 +1371,7 @@ int main(int argc, char **argv) {
|
|||||||
goto exit_and_close;
|
goto exit_and_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
prodos_rename_file(prodos_fd,apple_filename,new_filename);
|
prodos_rename_file(&voldir,apple_filename,new_filename);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -63,48 +63,12 @@ struct file_entry_t {
|
|||||||
unsigned short header_pointer;
|
unsigned short header_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CATALOG_VALUES */
|
|
||||||
#define CATALOG_NEXT_T 0x01
|
|
||||||
#define CATALOG_NEXT_S 0x02
|
|
||||||
#define CATALOG_FILE_LIST 0x0b
|
|
||||||
|
|
||||||
#define CATALOG_ENTRY_SIZE 0x23
|
|
||||||
|
|
||||||
/* CATALOG ENTRY */
|
|
||||||
#define FILE_TS_LIST_T 0x0
|
|
||||||
#define FILE_TS_LIST_S 0x1
|
|
||||||
#define FILE_TYPE 0x2
|
|
||||||
#define FILE_NAME 0x3
|
|
||||||
#define FILE_SIZE_L 0x21
|
|
||||||
#define FILE_SIZE_H 0x22
|
|
||||||
|
|
||||||
#define FILE_NAME_SIZE 0x1e
|
|
||||||
|
|
||||||
/* TSL */
|
|
||||||
#define TSL_NEXT_TRACK 0x1
|
|
||||||
#define TSL_NEXT_SECTOR 0x2
|
|
||||||
#define TSL_OFFSET_L 0x5
|
|
||||||
#define TSL_OFFSET_H 0x6
|
|
||||||
#define TSL_LIST 0xC
|
|
||||||
|
|
||||||
#define TSL_ENTRY_SIZE 0x2
|
|
||||||
#define TSL_MAX_NUMBER 122
|
|
||||||
|
|
||||||
/* Helper Macros */
|
|
||||||
#define TS_TO_INT(__x,__y) ((((int)__x)<<8)+__y)
|
|
||||||
#define DISK_OFFSET(__track,__sector) ((((__track)*BLOCKS_PER_TRACK)+(__sector))*PRODOS_BYTES_PER_BLOCK)
|
|
||||||
|
|
||||||
|
|
||||||
#define DOS33_FILE_NORMAL 0
|
|
||||||
#define DOS33_FILE_DELETED 1
|
|
||||||
|
|
||||||
/* prodos_volume_bitmap.c */
|
/* prodos_volume_bitmap.c */
|
||||||
int prodos_voldir_free_space(struct voldir_t *voldir);
|
int prodos_voldir_free_space(struct voldir_t *voldir);
|
||||||
int prodos_voldir_free_block(struct voldir_t *voldir, int block);
|
int prodos_voldir_free_block(struct voldir_t *voldir, int block);
|
||||||
int prodos_voldir_reserve_block(struct voldir_t *voldir, int block);
|
int prodos_voldir_reserve_block(struct voldir_t *voldir, int block);
|
||||||
void prodos_voldir_dump_bitmap(struct voldir_t *voldir);
|
void prodos_voldir_dump_bitmap(struct voldir_t *voldir);
|
||||||
int prodos_voldir_find_free_block(struct voldir_t *voldir,
|
int prodos_voldir_find_free_block(struct voldir_t *voldir);
|
||||||
int *found_block);
|
|
||||||
|
|
||||||
/* prodos_catalog.c */
|
/* prodos_catalog.c */
|
||||||
int prodos_find_next_file(int inode, struct voldir_t *voldir);
|
int prodos_find_next_file(int inode, struct voldir_t *voldir);
|
||||||
|
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
#include "prodos.h"
|
#include "prodos.h"
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
|
||||||
|
/* Note: PRODOS seems to label things this way */
|
||||||
|
/* block 0123 4567 */
|
||||||
|
/* 0x0f = 0000 1111 */
|
||||||
|
|
||||||
static int ones_lookup[16]={
|
static int ones_lookup[16]={
|
||||||
/* 0x0 = 0000 */ 0,
|
/* 0x0 = 0000 */ 0,
|
||||||
/* 0x1 = 0001 */ 1,
|
/* 0x1 = 0001 */ 1,
|
||||||
@ -22,6 +28,7 @@ static int ones_lookup[16]={
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* could be replaced by "find leading 1" instruction */
|
/* could be replaced by "find leading 1" instruction */
|
||||||
|
/* Note we are reverse from usual, wanting MSB first */
|
||||||
/* if available */
|
/* if available */
|
||||||
static int find_first_one(unsigned char byte) {
|
static int find_first_one(unsigned char byte) {
|
||||||
|
|
||||||
@ -29,7 +36,7 @@ static int find_first_one(unsigned char byte) {
|
|||||||
|
|
||||||
if (byte==0) return -1;
|
if (byte==0) return -1;
|
||||||
|
|
||||||
while((byte & (0x1<<i))==0) {
|
while((byte & (0x80>>i))==0) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
@ -58,52 +65,84 @@ int prodos_voldir_free_space(struct voldir_t *voldir) {
|
|||||||
return blocks_free;
|
return blocks_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free a sector from the sector bitmap */
|
/* free a block from the block bitmap */
|
||||||
int prodos_voldir_free_block(struct voldir_t *voldir, int block) {
|
int prodos_voldir_free_block(struct voldir_t *voldir, int block) {
|
||||||
|
|
||||||
#if 0
|
/* each volblock holds 512*8=4k entries */
|
||||||
/* each bitmap is 32 bits. With 16-sector tracks only first 16 used */
|
/* block location = block%4096 */
|
||||||
/* 1 indicates free, 0 indicates used */
|
/* which byte=remainder/8 */
|
||||||
if (sector<8) {
|
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+1]|=(0x1<<sector);
|
int volblock;
|
||||||
}
|
unsigned char temp_block[PRODOS_BYTES_PER_BLOCK];
|
||||||
else if (sector<16) {
|
unsigned char bitmap;
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+0]|=(0x1<<(sector-8));
|
int which_bitmap;
|
||||||
}
|
|
||||||
else if (sector<24) {
|
volblock=block/(PRODOS_BYTES_PER_BLOCK*8);
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+3]|=(0x1<<(sector-16));
|
|
||||||
}
|
prodos_read_block(voldir,temp_block,volblock+voldir->bit_map_pointer);
|
||||||
else if (sector<32) {
|
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+2]|=(0x1<<(sector-24));
|
which_bitmap=(block%(PRODOS_BYTES_PER_BLOCK*8))/8;
|
||||||
}
|
|
||||||
else {
|
bitmap=temp_block[which_bitmap];
|
||||||
fprintf(stderr,"Error vtoc_free_sector! sector too big %d\n",sector);
|
|
||||||
}
|
if (debug) {
|
||||||
#endif
|
printf("Free: $%X Using volblock %d (%d), flip b[%d]#%d $%X ",
|
||||||
|
block,volblock,volblock+voldir->bit_map_pointer,
|
||||||
|
which_bitmap,block&7,bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reserve a sector in the sector bitmap */
|
/* set bit to 1 to mark free */
|
||||||
|
bitmap|=(0x80>>(block&7));
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
printf("-> $%X\n",bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_block[which_bitmap]=bitmap;
|
||||||
|
|
||||||
|
prodos_write_block(voldir,temp_block,volblock+voldir->bit_map_pointer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reserve a block in the block bitmap */
|
||||||
int prodos_voldir_reserve_block(struct voldir_t *voldir, int block) {
|
int prodos_voldir_reserve_block(struct voldir_t *voldir, int block) {
|
||||||
|
|
||||||
#if 0
|
/* each volblock holds 512*8=4k entries */
|
||||||
/* each bitmap is 32 bits. With 16-sector tracks only first 16 used */
|
/* block location = block%4096 */
|
||||||
/* 1 indicates free, 0 indicates used */
|
/* which byte=remainder/8 */
|
||||||
if (sector<8) {
|
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+1]&=~(0x1<<sector);
|
int volblock;
|
||||||
|
unsigned char temp_block[PRODOS_BYTES_PER_BLOCK];
|
||||||
|
unsigned char bitmap;
|
||||||
|
int which_bitmap;
|
||||||
|
|
||||||
|
volblock=block/(PRODOS_BYTES_PER_BLOCK*8);
|
||||||
|
|
||||||
|
prodos_read_block(voldir,temp_block,volblock+voldir->bit_map_pointer);
|
||||||
|
|
||||||
|
which_bitmap=(block%(PRODOS_BYTES_PER_BLOCK*8))/8;
|
||||||
|
|
||||||
|
bitmap=temp_block[which_bitmap];
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
printf("Reserve: $%X Using volblock %d (%d), flip b[%d]#%d $%X ",
|
||||||
|
block,volblock,volblock+voldir->bit_map_pointer,
|
||||||
|
which_bitmap,block&7,bitmap);
|
||||||
}
|
}
|
||||||
else if (sector<16) {
|
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+0]&=~(0x1<<(sector-8));
|
/* clear bit to 0 to mark used */
|
||||||
|
bitmap&=~(0x80>>(block&7));
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
printf("-> $%X\n",bitmap);
|
||||||
}
|
}
|
||||||
else if (sector<24) {
|
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+3]&=~(0x1<<(sector-16));
|
temp_block[which_bitmap]=bitmap;
|
||||||
}
|
|
||||||
else if (sector<32) {
|
prodos_write_block(voldir,temp_block,volblock+voldir->bit_map_pointer);
|
||||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+2]&=~(0x1<<(sector-24));
|
|
||||||
}
|
return 0;
|
||||||
else {
|
|
||||||
fprintf(stderr,"Error vtoc_reserve_sector! sector too big %d\n",sector);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -151,87 +190,32 @@ void prodos_voldir_dump_bitmap(struct voldir_t *voldir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* reserve a sector in the sector bitmap */
|
/* find a free block in the block bitmap */
|
||||||
int prodos_voldir_find_free_block(struct voldir_t *voldir,
|
/* FIXME: for speed, remember last found block and start from there */
|
||||||
int *found_block) {
|
int prodos_voldir_find_free_block(struct voldir_t *voldir) {
|
||||||
|
|
||||||
#if 0
|
int volblocks;
|
||||||
int start_track,track_dir,i;
|
unsigned char temp_block[PRODOS_BYTES_PER_BLOCK];
|
||||||
int bitmap;
|
int i,k,result;
|
||||||
int found=0;
|
|
||||||
|
|
||||||
/* Originally used to keep things near center of disk for speed */
|
volblocks=1+voldir->total_blocks/(PRODOS_BYTES_PER_BLOCK*8);
|
||||||
/* We can use to avoid fragmentation possibly */
|
|
||||||
start_track=vtoc[VTOC_LAST_ALLOC_T]%TRACKS_PER_DISK;
|
|
||||||
track_dir=vtoc[VTOC_ALLOC_DIRECT];
|
|
||||||
|
|
||||||
if (track_dir==255) track_dir=-1;
|
for(k=0;k<volblocks;k++) {
|
||||||
|
|
||||||
if ((track_dir!=1) && (track_dir!=-1)) {
|
prodos_read_block(voldir,temp_block,k+voldir->bit_map_pointer);
|
||||||
fprintf(stderr,"ERROR! Invalid track dir %i\n",track_dir);
|
|
||||||
|
for(i=0;i<(512/16);i++) {
|
||||||
|
result=find_first_one(temp_block[i*2]);
|
||||||
|
if (result>=0) {
|
||||||
|
return (k<<4)+result;
|
||||||
}
|
}
|
||||||
|
result=find_first_one(temp_block[(1+i*2)]);
|
||||||
if (((start_track>PRODOS_VOLDIR_TRACK) && (track_dir!=1)) ||
|
if (result>=0) {
|
||||||
((start_track<PRODOS_VOLDIR_TRACK) && (track_dir!=-1))) {
|
return (k<<4)+result+8;
|
||||||
fprintf(stderr,"Warning! Non-optimal values for track dir t=%i d=%i\n",
|
|
||||||
start_track,track_dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i=start_track;
|
|
||||||
do {
|
|
||||||
|
|
||||||
/* i+1 = sector 0..7 */
|
|
||||||
bitmap=vtoc[VTOC_FREE_BITMAPS+(i*4)+1];
|
|
||||||
if (bitmap!=0x00) {
|
|
||||||
*found_sector=find_first_one(bitmap);
|
|
||||||
*found_track=i;
|
|
||||||
found++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* i+0 = sector 8..15 */
|
|
||||||
bitmap=vtoc[VTOC_FREE_BITMAPS+(i*4)];
|
|
||||||
if (bitmap!=0x00) {
|
|
||||||
*found_sector=find_first_one(bitmap)+8;
|
|
||||||
*found_track=i;
|
|
||||||
found++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move to next track, handling overflows */
|
|
||||||
i+=track_dir;
|
|
||||||
if (i<0) {
|
|
||||||
i=PRODOS_VOLDIR_TRACK;
|
|
||||||
track_dir=1;
|
|
||||||
}
|
|
||||||
if (i>=TRACKS_PER_DISK) {
|
|
||||||
i=PRODOS_VOLDIR_TRACK;
|
|
||||||
track_dir=-1;
|
|
||||||
}
|
|
||||||
} while (i!=start_track);
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
/* clear bit indicating in use */
|
|
||||||
prodos_voldir_reserve_sector(voldir, *found_track, *found_sector);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* write modified VTOC back out */
|
|
||||||
lseek(fd,DISK_OFFSET(PRODOS_VOLDIR_TRACK,PRODOS_VOLDIR_BLOCK),SEEK_SET);
|
|
||||||
result=write(fd,&voldir,PRODOS_BYTES_PER_BLOCK);
|
|
||||||
|
|
||||||
if (result<0) {
|
|
||||||
fprintf(stderr,"Error on I/O\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* no room */
|
/* no room */
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user