xref: /freebsd/usr.sbin/fdwrite/fdwrite.c (revision 17ee9d00bc1ae1e598c38f25826f861e4bc6c3ce)
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dkuug.dk> 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  * $Id: fdwrite.c,v 1.1.1.1 1994/09/18 07:39:19 phk Exp $
10  *
11  */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <strings.h>
18 #include <ctype.h>
19 
20 #include <errno.h>
21 #include <machine/ioctl_fd.h>
22 
23 int
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     register 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
57 usage ()
58 {
59 	printf("Usage:\n\tfdwrite [-v] [-f inputfile] [-d device]\n");
60 	exit(2);
61 }
62 
63 int
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     char *device= "/dev/rfd0", *trackbuf = 0,*vrfybuf = 0;
69     struct fd_type fdt;
70     FILE *tty;
71 
72     setbuf(stdout,0);
73     while((c = getopt(argc, argv, "d:s:f:v")) != -1)
74 	    switch(c) {
75 	    case 'd':	/* Which drive */
76 		    device = optarg;
77 		    break;
78 
79 	    case 'f':	/* input file */
80 		    if (inputfd >= 0)
81 			    close(inputfd);
82 		    inputfd = open(optarg,O_RDONLY);
83 		    if (inputfd < 0) {
84 			    perror(optarg);
85 			    exit(1);
86 		    }
87 		    break;
88 
89 	    case 'v':  /* Toggle verbosity */
90 		    verbose = !verbose;
91 		    break;
92 
93 	    case '?': default:
94 		    usage();
95 	    }
96 
97     if (inputfd < 0)
98 	inputfd = 0;
99 
100     if(optind < argc)
101 	    usage();
102 
103     tty = fopen("/dev/tty","r+");
104     if(!tty) {
105 	    perror("/dev/tty");
106 	    exit(1);
107     }
108     setbuf(tty,0);
109 
110     for(j=1;j > 0;) {
111         fdn++;
112 	fprintf(tty,
113 	    "Please insert floppy #%d in drive %s and press return >",
114 		fdn,device);
115 	while(1) {
116 	    i = getc(tty);
117 	    if(i == '\n') break;
118 	}
119 
120 	if((fd = open(device, O_RDWR)) < 0) {
121 	    perror(device);
122 	    exit(1);
123 	}
124 
125 	if(ioctl(fd, FD_GTYPE, &fdt) < 0) {
126 	    fprintf(stderr, "fdformat: not a floppy disk: %s\n", device);
127 	    exit(1);
128 	}
129 
130 	bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
131 	if(!trackbuf) {
132 	    trackbuf = malloc(bpt);
133 	    if(!trackbuf) { perror("malloc"); exit(1); }
134 	}
135 	if(!vrfybuf) {
136 	    vrfybuf = malloc(bpt);
137 	    if(!vrfybuf) { perror("malloc"); exit(1); }
138 	}
139 
140 	if(fdn == 1) {
141 	    if(verbose) {
142 		printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
143 		fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
144 		fdt.tracks*bpt*fdt.heads/1024);
145 
146 	    }
147 	    memset(trackbuf,0,bpt);
148 	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
149 		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
150 		    close(inputfd);
151 		    inputfd = -1;
152 		    break;
153 		}
154 		nbytes += i;
155 	    }
156 	}
157 	for (track = 0; track < fdt.tracks * fdt.heads; track++) {
158 	    if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
159 	    if(verbose) putc((j ? 'I':'Z'),stdout);
160 	    format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
161 		    fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
162 		    fdt.f_inter);
163 	    if(verbose) putc('F',stdout);
164 
165 	    if (lseek (fd, (long) track*bpt, 0) < 0) {
166 		perror("lseek");
167 		exit (1);
168 	    }
169 	    if (write (fd, trackbuf, bpt) != bpt) {
170 		perror("write");
171 		exit (1);
172 	    }
173 	    if(verbose) putc('W',stdout);
174 
175 	    if (lseek (fd, (long) track*bpt, 0) < 0) {
176 		perror("lseek");
177 		exit (1);
178 	    }
179 	    if (read (fd, vrfybuf, bpt) != bpt) {
180 		perror("read");
181 		exit (1);
182 	    }
183 	    if(verbose) putc('R',stdout);
184 
185 	    if (memcmp(trackbuf,vrfybuf,bpt)) {
186 		perror("compare");
187 		exit (1);
188 	    }
189 	    if(verbose) putc('C',stdout);
190 
191 	    memset(trackbuf,0,bpt);
192 	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
193 		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
194 		    close(inputfd);
195 		    inputfd = -1;
196 		    break;
197 		}
198 		nbytes += i;
199 	    }
200 	}
201 	close(fd);
202 	putc('\r',stdout);
203     }
204     if(verbose)
205 	printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
206     exit(0);
207 }
208