prodos: enable setting create/modify time

This commit is contained in:
Vince Weaver 2021-08-03 17:05:05 -04:00
parent b99cdc1ee7
commit c84a801d49
10 changed files with 135 additions and 31 deletions

View File

@ -11,13 +11,15 @@ prodos: prodos.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o \
prodos_voldir.o
prodos_voldir.o \
prodos_time.o
$(CC) -o prodos prodos.o \
prodos_read.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o \
prodos_voldir.o $(LFLAGS)
prodos_voldir.o \
prodos_time.o $(LFLAGS)
prodos.o: prodos.c prodos.h
$(CC) $(CFLAGS) -g -c prodos.c
@ -49,10 +51,10 @@ text_to_prodos.o: text_to_prodos.c
###
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o
prodos_voldir.o prodos_time.o
$(CC) $(LFLAGS) -o mkprodosfs mkprodosfs.o \
prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o
prodos_voldir.o prodos_time.o
mkprodosfs.o: mkprodosfs.c prodos.h
$(CC) $(CFLAGS) -c mkprodosfs.c
@ -82,6 +84,11 @@ prodos_read.o: prodos_read.c prodos.h
prodos_voldir.o: prodos_voldir.c prodos.h
$(CC) $(CFLAGS) -c prodos_voldir.c
###
prodos_time.o: prodos_time.c prodos.h
$(CC) $(CFLAGS) -c prodos_time.c
###

View File

@ -8,6 +8,9 @@ Tools for manipulating Apple II prodos filesystems
+ mkprodosfs: create an Apple ][ ProDOS filesystems
+ prodos_cat : allow cat'ing (listing) prodos text files with \r (CR)
line endings on a machine like Linux that's expecting \n (LF)
NOTE: subdirectory support is currently not implemented
TODO:

View File

@ -4,12 +4,13 @@
#include <unistd.h> /* close() */
#include <stdlib.h> /* strtol() */
#include <errno.h>
#include <time.h>
#include "version.h"
#include "prodos.h"
int debug=1;
int debug=0;
static int ones_lookup[8]={
0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF,
@ -134,7 +135,7 @@ int main(int argc, char **argv) {
voldir.bit_map_pointer=6;
voldir.creation_time=0;
voldir.creation_time=prodos_time(time(NULL));
voldir.file_count=0;

View File

@ -6,14 +6,14 @@
#include <unistd.h> /* lseek() */
#include <ctype.h> /* toupper() */
#include <errno.h>
#include <time.h>
#include "version.h"
#include "prodos.h"
static int ignore_errors=0;
int debug=1;
int debug=0;
/* Given filename, return voldir/offset */
static int prodos_lookup_file(struct voldir_t *voldir,
@ -207,6 +207,21 @@ static int prodos_writeout_filedesc(struct voldir_t *voldir,
#define ERROR_FILE_TOO_BIG 7
#define PRODOS_NUM_FILE_TYPES 5
static struct prodos_file_type {
int type;
char name[4];
} file_types[PRODOS_NUM_FILE_TYPES] = {
{PRODOS_TYPE_TXT,"TXT"},
{PRODOS_TYPE_BIN,"BIN"},
{PRODOS_TYPE_BAS,"BAS"},
{PRODOS_TYPE_VAR,"VAR"},
{PRODOS_TYPE_SYS,"SYS"},
};
/* creates file apple_filename on the image from local file filename */
/* returns ?? */
static int prodos_add_file(struct voldir_t *voldir,
@ -215,7 +230,7 @@ static int prodos_add_file(struct voldir_t *voldir,
char *filename, char *apple_filename) {
int free_blocks,file_size,needed_blocks,total_blocks,file_type;
int free_blocks,file_size,needed_blocks,total_blocks,storage_type;
int block,i,j,needed_limit;
struct stat file_info;
int input_fd;
@ -225,6 +240,8 @@ static int prodos_add_file(struct voldir_t *voldir,
unsigned char data_buffer[PRODOS_BYTES_PER_BLOCK];
int key_block,index,inode;
struct file_entry_t file;
int file_type=0;
/* check for valid filename */
@ -247,6 +264,14 @@ static int prodos_add_file(struct voldir_t *voldir,
}
}
/* get file type */
for(i=0;i<PRODOS_NUM_FILE_TYPES;i++) {
if (!strncmp(type,file_types[i].name,3)) {
file_type=file_types[i].type;
if (debug) printf("Found type %s=%d\n",type,file_type);
}
}
/* Determine size of file to upload */
if (stat(filename,&file_info)<0) {
fprintf(stderr,"Error! %s not found!\n",filename);
@ -269,19 +294,19 @@ static int prodos_add_file(struct voldir_t *voldir,
else if (needed_blocks==1) {
/* seedling */
if (debug) printf("File seedling\n");
file_type=PRODOS_FILE_SEEDLING;
storage_type=PRODOS_FILE_SEEDLING;
total_blocks=needed_blocks;
}
else if (needed_blocks<=256) {
/* sapling */
if (debug) printf("File sapling\n");
file_type=PRODOS_FILE_SAPLING;
storage_type=PRODOS_FILE_SAPLING;
total_blocks=needed_blocks+1; /* for index block */
}
else if (needed_blocks<=65536) {
/* tree */
if (debug) printf("File tree\n");
file_type=PRODOS_FILE_TREE;
storage_type=PRODOS_FILE_TREE;
total_blocks=needed_blocks+1 /* for key index block */
+(1+needed_blocks/256); /* for index blocks */
/* FIXME: -1? */
@ -309,7 +334,7 @@ static int prodos_add_file(struct voldir_t *voldir,
return ERROR_IMAGE_NOT_FOUND;
}
if (file_type==PRODOS_FILE_SEEDLING) {
if (storage_type==PRODOS_FILE_SEEDLING) {
block=prodos_allocate_block(voldir);
key_block=block;
@ -322,7 +347,7 @@ static int prodos_add_file(struct voldir_t *voldir,
prodos_write_block(voldir,data_buffer,block);
}
if (file_type==PRODOS_FILE_SAPLING) {
if (storage_type==PRODOS_FILE_SAPLING) {
/* allocate index */
index=prodos_allocate_block(voldir);
key_block=index;
@ -348,7 +373,7 @@ static int prodos_add_file(struct voldir_t *voldir,
}
if (file_type==PRODOS_FILE_TREE) {
if (storage_type==PRODOS_FILE_TREE) {
/* allocate key index */
key_block=prodos_allocate_block(voldir);
memset(key_buffer,0,PRODOS_BYTES_PER_BLOCK);
@ -395,19 +420,19 @@ static int prodos_add_file(struct voldir_t *voldir,
/* FIXME */
file.storage_type=file_type;
file.storage_type=storage_type;
file.name_length=strlen(apple_filename);
memcpy(file.file_name,apple_filename,file.name_length);
file.file_type=0;
file.file_type=file_type;
file.key_pointer=key_block;
file.blocks_used=total_blocks; /* includes index blocks */
file.eof=file_size;
file.creation_time=0;
file.creation_time=prodos_time(time(NULL));
file.version=0;
file.min_version=0;
file.access=0;
file.aux_type=0;
file.last_mod=0;
file.last_mod=prodos_time(time(NULL));
file.header_pointer=PRODOS_VOLDIR_KEY_BLOCK;
@ -416,6 +441,8 @@ static int prodos_add_file(struct voldir_t *voldir,
return inode;
}
if (debug) printf("Found inode $%x\n",inode);
/* read in existing voldir entry */
result=prodos_read_block(voldir,data_buffer,inode>>8);
@ -427,6 +454,7 @@ static int prodos_add_file(struct voldir_t *voldir,
result=prodos_write_block(voldir,data_buffer,inode>>8);
/* update file count */
if (debug) printf("Updating file count...\n");
voldir->file_count++;
prodos_sync_voldir(voldir);
@ -1048,7 +1076,7 @@ int main(int argc, char **argv) {
interleave=arg_interleave-1;
}
prodos_read_voldir(prodos_fd,&voldir,interleave,image_offset);
prodos_init_voldir(prodos_fd,&voldir,interleave,image_offset);
/* Move to next argument */
optind++;

View File

@ -91,5 +91,9 @@ int prodos_write_block(struct voldir_t *voldir,unsigned char *block, int blocknu
/* 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 prodos_init_voldir(int fd, struct voldir_t *voldir,
int interleave, int image_offset);
int prodos_read_voldir(struct voldir_t *voldir);
/* prodos_time.c */
int prodos_time(time_t t);

View File

@ -2,6 +2,7 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "prodos.h"
@ -129,7 +130,7 @@ static int prodos_text_timestamp(int t, unsigned char *timestamp) {
minute=t&0x3f;
sprintf((char *)timestamp,"%2d-%s-%02d %2d:%02d",
day,prodos_capital_month_names[month],year,hour,minute);
day,prodos_capital_month_names[month],year%100,hour,minute);
timestamp[16]=0;
return 0;

View File

@ -3,6 +3,7 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include "version.h"

View File

@ -0,0 +1,38 @@
#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 <time.h>
#include "version.h"
#include "prodos.h"
extern int debug;
int prodos_time(time_t t) {
struct tm *broken_time;
int pyear,pmonth,pday,phour,pminute;
int ptime;
broken_time=localtime(&t);
pyear=broken_time->tm_year;
pmonth=broken_time->tm_mon;
pday=broken_time->tm_mday;
phour=broken_time->tm_hour;
pminute=broken_time->tm_min;
ptime=(pyear<<25)|(pmonth<<21)|(pday<<16)|(phour<<8)|pminute;
if (debug) printf("Y=%d M=%d D=%d h=%d m=%d\n",
pyear,pmonth,pday,phour,pminute);
return ptime;
}

View File

@ -13,18 +13,14 @@
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 prodos_read_voldir(struct voldir_t *voldir) {
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) {
@ -32,8 +28,6 @@ int prodos_read_voldir(int fd, struct voldir_t *voldir,
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) {
@ -68,12 +62,38 @@ int prodos_read_voldir(int fd, struct voldir_t *voldir,
}
/* 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];
memset(newvoldir,0,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);

View File

@ -1,4 +1,5 @@
#include <stdio.h>
#include <time.h>
#include "prodos.h"