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