mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-11-01 16:04:55 +00:00
257 lines
5.9 KiB
C
257 lines
5.9 KiB
C
#include <stdio.h>
|
|
#include <string.h> /* strncpy() */
|
|
#include <fcntl.h> /* open() */
|
|
#include <unistd.h> /* close() */
|
|
#include <stdlib.h> /* strtol() */
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
|
|
#include "version.h"
|
|
|
|
#include "prodos.h"
|
|
|
|
int debug=0;
|
|
|
|
static int ones_lookup[8]={
|
|
0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF,
|
|
};
|
|
|
|
static void usage(char *binary,int help) {
|
|
|
|
printf("\n%s - version %s\n",binary,VERSION);
|
|
printf("\tby Vince Weaver <vince@deater.net>\n");
|
|
printf("\thttp://www.deater.net/weave/vmwprod/apple/\n\n");
|
|
if (help) {
|
|
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("\t-2 : prepend a 2mg header\n");
|
|
printf("\n\n");
|
|
}
|
|
exit(0);
|
|
return;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int num_blocks=280;
|
|
int fd;
|
|
char device[BUFSIZ];
|
|
char *endptr;
|
|
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;
|
|
int make_2mg_header=0;
|
|
unsigned char header_2mg[64];
|
|
|
|
strncpy(volname,"EMPTY",6);
|
|
volname_len=strlen(volname);
|
|
|
|
/* Parse Command Line Arguments */
|
|
|
|
while ((c = getopt (argc, argv,"b:i:s:n:hv2"))!=-1) {
|
|
switch (c) {
|
|
case 'b':
|
|
num_blocks=strtol(optarg,&endptr,10);
|
|
if ( endptr == optarg ) usage(argv[0], 1);
|
|
break;
|
|
case 'i':
|
|
if (!strncasecmp(optarg,"prodos",6)) {
|
|
interleave=PRODOS_INTERLEAVE_PRODOS;
|
|
}
|
|
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 '2': make_2mg_header=1;
|
|
break;
|
|
case 'v': usage(argv[0],0);
|
|
case 'h': usage(argv[0],1);
|
|
|
|
}
|
|
}
|
|
|
|
if (optind==argc) {
|
|
printf("Error! Must include device name\n\n");
|
|
goto end_of_program;
|
|
}
|
|
|
|
strncpy(device,argv[optind],BUFSIZ-1);
|
|
|
|
/***********************/
|
|
/* Sanity check values */
|
|
/***********************/
|
|
|
|
/* sectors: 2->32 (limited by 4-byte bitfields) */
|
|
if ((num_blocks<6) || (num_blocks>65535)) {
|
|
printf("Number of blocks must be >6 and <65536\n\n");
|
|
goto end_of_program;
|
|
}
|
|
|
|
/* Open device */
|
|
fd=open(device,O_RDWR|O_CREAT|O_TRUNC,0666);
|
|
if (fd<0) {
|
|
fprintf(stderr,"Error opening %s (%s)\n",
|
|
device,strerror(errno));
|
|
goto end_of_program;
|
|
}
|
|
|
|
|
|
/*****************/
|
|
/* init voldir */
|
|
/*****************/
|
|
|
|
memset(&voldir,0,sizeof(struct voldir_t));
|
|
|
|
voldir.fd=fd;
|
|
voldir.interleave=interleave;
|
|
|
|
if (make_2mg_header) {
|
|
|
|
create_2mg_header(header_2mg,num_blocks);
|
|
|
|
write(fd,header_2mg,64);
|
|
|
|
voldir.image_offset=64;
|
|
}
|
|
else {
|
|
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;
|
|
|
|
voldir.bit_map_pointer=6;
|
|
|
|
voldir.creation_time=prodos_time(time(NULL));
|
|
|
|
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 {
|
|
ones_to_write=num_blocks%(512*8);
|
|
}
|
|
|
|
if (debug) printf("Writing %d ones\n",ones_to_write);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/*********************************/
|
|
/* reserve all of the used space */
|
|
/*********************************/
|
|
|
|
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
|
|
}
|
|
|
|
/*********************************/
|
|
/* write out voldir */
|
|
/*********************************/
|
|
prodos_sync_voldir(&voldir);
|
|
|
|
close(fd);
|
|
|
|
end_of_program:
|
|
|
|
return 0;
|
|
}
|