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