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