1 /*-
2 * SPDX-License-Identifier: Beerware
3 *
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 *
11 */
12
13 #include <err.h>
14 #include <fcntl.h>
15 #include <paths.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 #include <sys/fdcio.h>
22
23 static int
format_track(int fd,int cyl,int secs,int head,int rate,int gaplen,int secsize,int fill,int interleave)24 format_track(int fd, int cyl, int secs, int head, int rate,
25 int gaplen, int secsize, int fill, int interleave)
26 {
27 struct fd_formb f;
28 int i, j;
29 int il[100];
30
31 memset(il,0,sizeof il);
32 for(j = 0, i = 1; i <= secs; i++) {
33 while(il[(j%secs)+1]) j++;
34 il[(j%secs)+1] = i;
35 j += interleave;
36 }
37
38 f.format_version = FD_FORMAT_VERSION;
39 f.head = head;
40 f.cyl = cyl;
41 f.transfer_rate = rate;
42
43 f.fd_formb_secshift = secsize;
44 f.fd_formb_nsecs = secs;
45 f.fd_formb_gaplen = gaplen;
46 f.fd_formb_fillbyte = fill;
47 for(i = 0; i < secs; i++) {
48 f.fd_formb_cylno(i) = cyl;
49 f.fd_formb_headno(i) = head;
50 f.fd_formb_secno(i) = il[i+1];
51 f.fd_formb_secsize(i) = secsize;
52 }
53 return ioctl(fd, FD_FORM, (caddr_t)&f);
54 }
55
56 static void
usage(void)57 usage(void)
58 {
59 fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n");
60 exit(2);
61 }
62
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66 int inputfd = -1, c, fdn = 0, i,j,fd;
67 int bpt, verbose=1, nbytes=0, track;
68 int interactive = 1;
69 const char *device= "/dev/fd0";
70 char *trackbuf = NULL, *vrfybuf = NULL;
71 struct fd_type fdt;
72 FILE *tty;
73
74 setbuf(stdout,0);
75 while((c = getopt(argc, argv, "d:f:vy")) != -1)
76 switch(c) {
77 case 'd': /* Which drive */
78 device = optarg;
79 break;
80
81 case 'f': /* input file */
82 if (inputfd >= 0)
83 close(inputfd);
84 inputfd = open(optarg,O_RDONLY);
85 if (inputfd < 0)
86 err(1, "%s", optarg);
87 break;
88
89 case 'v': /* Toggle verbosity */
90 verbose = !verbose;
91 break;
92
93 case 'y': /* Don't confirm? */
94 interactive = 0;
95 break;
96
97 case '?': default:
98 usage();
99 }
100
101 if (inputfd < 0)
102 inputfd = 0;
103
104 if (!isatty(1))
105 interactive = 0;
106
107 if(optind < argc)
108 usage();
109
110 tty = fopen(_PATH_TTY,"r+");
111 if(!tty)
112 err(1, _PATH_TTY);
113 setbuf(tty,0);
114
115 for(j=1;j > 0;) {
116 fdn++;
117 if (interactive) {
118 fprintf(tty,
119 "Please insert floppy #%d in drive %s and press return >",
120 fdn,device);
121 while(1) {
122 i = getc(tty);
123 if(i == '\n') break;
124 }
125 }
126
127 if((fd = open(device, O_RDWR)) < 0)
128 err(1, "%s", device);
129
130 if(ioctl(fd, FD_GTYPE, &fdt) < 0)
131 errx(1, "not a floppy disk: %s", device);
132
133 bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
134 if(!trackbuf) {
135 trackbuf = malloc(bpt);
136 if(!trackbuf) errx(1, "malloc");
137 }
138 if(!vrfybuf) {
139 vrfybuf = malloc(bpt);
140 if(!vrfybuf) errx(1, "malloc");
141 }
142
143 if(fdn == 1) {
144 if(verbose) {
145 printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
146 fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
147 fdt.tracks*bpt*fdt.heads/1024);
148
149 }
150 memset(trackbuf,0,bpt);
151 for(j=0;inputfd >= 0 && j<bpt;j+=i) {
152 if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
153 close(inputfd);
154 inputfd = -1;
155 break;
156 }
157 nbytes += i;
158 }
159 }
160 for (track = 0; track < fdt.tracks * fdt.heads; track++) {
161 if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
162 if(verbose) putc((j ? 'I':'Z'),stdout);
163 format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
164 fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
165 fdt.f_inter);
166 if(verbose) putc('F',stdout);
167
168 if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
169 if (write (fd, trackbuf, bpt) != bpt) err(1, "write");
170 if(verbose) putc('W',stdout);
171
172 if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
173 if (read (fd, vrfybuf, bpt) != bpt) err(1, "read");
174 if(verbose) putc('R',stdout);
175
176 if (memcmp(trackbuf,vrfybuf,bpt)) err(1, "compare");
177 if(verbose) putc('C',stdout);
178
179 memset(trackbuf,0,bpt);
180 for(j=0;inputfd >= 0 && j<bpt;j+=i) {
181 if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
182 close(inputfd);
183 inputfd = -1;
184 break;
185 }
186 nbytes += i;
187 }
188 }
189 close(fd);
190 putc('\r',stdout);
191 }
192 if(verbose)
193 printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
194
195 free(trackbuf);
196 free(vrfybuf);
197 exit(0);
198 }
199