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 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 62 usage(void) 63 { 64 fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n"); 65 exit(2); 66 } 67 68 int 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