dos33fsprogs/utils/prodos-utils/prodos_voldir.c

152 lines
3.8 KiB
C

#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(struct voldir_t *voldir) {
int result;
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
/* read in VOLDIR KEY Block*/
result=prodos_read_block(voldir,voldir_buffer,PRODOS_VOLDIR_KEY_BLOCK);
if (result<0) {
fprintf(stderr,"Error reading VOLDIR\n");
return -1;
}
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;
}
/* Read volume directory into a buffer */
int prodos_init_voldir(int fd, struct voldir_t *voldir,
int interleave, int image_offset) {
voldir->interleave=interleave;
voldir->image_offset=image_offset;
/* read in VOLDIR KEY Block*/
voldir->fd=fd;
prodos_read_voldir(voldir);
return 0;
}
/* write out the voldir */
/* This is tricky as the superblock-type info is entry 0 */
/* but the rest are directory entries */
/* and we sort of treat these as separate but not */
int prodos_sync_voldir(struct voldir_t *voldir) {
unsigned char newvoldir[PRODOS_BYTES_PER_BLOCK];
/* read in existing voldir */
prodos_read_block(voldir,newvoldir,PRODOS_VOLDIR_KEY_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;
}