Imported Upstream version 2.1
[debian/cpmtools] / mkfs.cpm.c
1 /* #includes */ /*{{{C}}}*//*{{{*/
2 #include <ctype.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "config.h"
8
9 extern char *optarg;
10 extern int optind,opterr,optopt;
11 int getopt(int argc, char * const *argv, const char *optstring);
12
13 #include "cpmfs.h"
14 /*}}}*/
15 /* #defines */ /*{{{*/
16 #ifndef O_BINARY
17 #define O_BINARY 0
18 #endif
19 /*}}}*/
20
21 /* mkfs -- make file system */ /*{{{*/
22 static int mkfs(struct cpmSuperBlock *drive, const char *name, const char *label, char *bootTracks)
23 {
24   /* variables */ /*{{{*/
25   int i;
26   char buf[128];
27   char firstbuf[128];
28   int fd;
29   int bytes;
30   int trkbytes;
31   /*}}}*/
32
33   /* open image file */ /*{{{*/
34   if ((fd = open(name, O_BINARY|O_CREAT|O_WRONLY, 0666)) < 0)
35   {
36     boo=strerror(errno);
37     return -1;
38   }
39   /*}}}*/
40   /* write system tracks */ /*{{{*/
41   /* this initialises only whole tracks, so it skew is not an issue */
42   trkbytes=drive->secLength*drive->sectrk;
43   for (i=0; i<trkbytes*drive->boottrk; i+=drive->secLength) if (write(fd, bootTracks+i, drive->secLength)!=drive->secLength)
44   {
45     boo=strerror(errno);
46     close(fd);
47     return -1;
48   }
49   /*}}}*/
50   /* write directory */ /*{{{*/
51   memset(buf,0xe5,128);
52   bytes=drive->maxdir*32;
53   if (bytes%trkbytes) bytes=((bytes+trkbytes)/trkbytes)*trkbytes;
54   if (drive->type==CPMFS_P2DOS || drive->type==CPMFS_DR3) buf[3*32]=0x21;
55   memcpy(firstbuf,buf,128);
56   if (drive->type==CPMFS_DR3)
57   {
58     time_t now;
59     struct tm *t;
60     int min,hour,days;
61
62     firstbuf[0]=0x20;
63     for (i=0; i<11 && *label; ++i,++label) firstbuf[1+i]=toupper(*label&0x7f);
64     while (i<11) firstbuf[1+i++]=' ';
65     firstbuf[12]=0x11; /* label set and first time stamp is creation date */
66     memset(&firstbuf[13],0,1+2+8);
67     time(&now);
68     t=localtime(&now);
69     min=((t->tm_min/10)<<4)|(t->tm_min%10);
70     hour=((t->tm_hour/10)<<4)|(t->tm_hour%10);
71     for (i=1978,days=0; i < 1900 + t->tm_year; ++i)
72     {
73       days+=365;
74       if (i%4==0 && (i%100!=0 || i%400==0)) ++days;
75     }
76     days += t->tm_yday + 1;
77     firstbuf[24]=firstbuf[28]=days&0xff; firstbuf[25]=firstbuf[29]=days>>8;
78     firstbuf[26]=firstbuf[30]=hour;
79     firstbuf[27]=firstbuf[31]=min;
80   }
81   for (i=0; i < bytes; i += 128) if (write(fd, i==0 ? firstbuf : buf, 128)!=128)
82   {
83     boo=strerror(errno);
84     close(fd);
85     return -1;
86   }
87   /*}}}*/
88   /* close image file */ /*{{{*/
89   if (close(fd)==-1)
90   {
91     boo=strerror(errno);
92     return -1;
93   }
94   /*}}}*/
95   return 0;
96 }
97 /*}}}*/
98
99 const char cmd[]="mkfs.cpm";
100
101 int main(int argc, char *argv[]) /*{{{*/
102 {
103   char *image;
104   const char *format=FORMAT;
105   int c,usage=0;
106   struct cpmSuperBlock drive;
107   struct cpmInode root;
108   const char *label="unlabeled";
109   size_t bootTrackSize,used;
110   char *bootTracks;
111   const char *boot[4]={(const char*)0,(const char*)0,(const char*)0,(const char*)0};
112
113   while ((c=getopt(argc,argv,"b:f:L:h?"))!=EOF) switch(c)
114   {
115     case 'b':
116     {
117       if (boot[0]==(const char*)0) boot[0]=optarg;
118       else if (boot[1]==(const char*)0) boot[1]=optarg;
119       else if (boot[2]==(const char*)0) boot[2]=optarg;
120       else if (boot[3]==(const char*)0) boot[3]=optarg;
121       else usage=1;
122       break;
123     }
124     case 'f': format=optarg; break;
125     case 'L': label=optarg; break;
126     case 'h':
127     case '?': usage=1; break;
128   }
129
130   if (optind!=(argc-1)) usage=1;
131   else image=argv[optind];
132
133   if (usage)
134   {
135     fprintf(stderr,"Usage: %s [-f format] [-b boot] [-L label] image\n",cmd);
136     exit(1);
137   }
138   drive.dev.opened=0;
139   cpmReadSuper(&drive,&root,format);
140   bootTrackSize=drive.boottrk*drive.secLength*drive.sectrk;
141   if ((bootTracks=malloc(bootTrackSize))==(void*)0)
142   {
143     fprintf(stderr,"%s: can not allocate boot track buffer: %s\n",cmd,strerror(errno));
144     exit(1);
145   }
146   memset(bootTracks,0xe5,bootTrackSize);
147   used=0; 
148   for (c=0; c<4 && boot[c]; ++c)
149   {
150     int fd;
151     size_t size;
152
153     if ((fd=open(boot[c],O_BINARY|O_RDONLY))==-1)
154     {
155       fprintf(stderr,"%s: can not open %s: %s\n",cmd,boot[c],strerror(errno));
156       exit(1);
157     }
158     size=read(fd,bootTracks+used,bootTrackSize-used);
159 #if 0
160     fprintf(stderr,"%d %04x %s\n",c,used+0x800,boot[c]);
161 #endif
162     if (size%drive.secLength) size=(size|(drive.secLength-1))+1;
163     used+=size;
164     close(fd);
165   }
166   if (mkfs(&drive,image,label,bootTracks)==-1)
167   {
168     fprintf(stderr,"%s: can not make new file system: %s\n",cmd,boo);
169     exit(1);
170   }
171   else exit(0);
172 }
173 /*}}}*/