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