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