xref: /dflybsd-src/usr.sbin/fdwrite/fdwrite.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * ----------------------------------------------------------------------------
386d7f5d3SJohn Marino  * "THE BEER-WARE LICENSE" (Revision 42):
486d7f5d3SJohn Marino  * <phk@login.dkuug.dk> wrote this file.  As long as you retain this notice you
586d7f5d3SJohn Marino  * can do whatever you want with this stuff. If we meet some day, and you think
686d7f5d3SJohn Marino  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
786d7f5d3SJohn Marino  * ----------------------------------------------------------------------------
886d7f5d3SJohn Marino  *
986d7f5d3SJohn Marino  * $FreeBSD: src/usr.sbin/fdwrite/fdwrite.c,v 1.8.2.3 2001/07/19 13:21:19 joerg Exp $
1086d7f5d3SJohn Marino  * $DragonFly: src/usr.sbin/fdwrite/fdwrite.c,v 1.5 2004/12/03 22:51:47 liamfoy Exp $
1186d7f5d3SJohn Marino  *
1286d7f5d3SJohn Marino  */
1386d7f5d3SJohn Marino 
1486d7f5d3SJohn Marino #include <ctype.h>
1586d7f5d3SJohn Marino #include <err.h>
1686d7f5d3SJohn Marino #include <fcntl.h>
1786d7f5d3SJohn Marino #include <paths.h>
1886d7f5d3SJohn Marino #include <stdio.h>
1986d7f5d3SJohn Marino #include <stdlib.h>
2086d7f5d3SJohn Marino #include <string.h>
2186d7f5d3SJohn Marino #include <unistd.h>
2286d7f5d3SJohn Marino 
2386d7f5d3SJohn Marino #include <machine/ioctl_fd.h>
2486d7f5d3SJohn Marino 
2586d7f5d3SJohn Marino static int	format_track(int, int, int, int, int,
2686d7f5d3SJohn Marino 				int, int, int, int);
2786d7f5d3SJohn Marino 
2886d7f5d3SJohn Marino static int
format_track(int fd,int cyl,int secs,int head,int rate,int gaplen,int secsize,int fill,int interleave)2986d7f5d3SJohn Marino format_track(int fd, int cyl, int secs, int head, int rate,
3086d7f5d3SJohn Marino              int gaplen, int secsize, int fill,int interleave)
3186d7f5d3SJohn Marino {
3286d7f5d3SJohn Marino     struct fd_formb f;
3386d7f5d3SJohn Marino     int i, j;
3486d7f5d3SJohn Marino     int il[100];
3586d7f5d3SJohn Marino 
3686d7f5d3SJohn Marino     memset(il,0,sizeof il);
3786d7f5d3SJohn Marino     for(j = 0, i = 1; i <= secs; i++) {
3886d7f5d3SJohn Marino 	while(il[(j%secs)+1]) j++;
3986d7f5d3SJohn Marino 	il[(j%secs)+1] = i;
4086d7f5d3SJohn Marino 	j += interleave;
4186d7f5d3SJohn Marino     }
4286d7f5d3SJohn Marino 
4386d7f5d3SJohn Marino     f.format_version = FD_FORMAT_VERSION;
4486d7f5d3SJohn Marino     f.head = head;
4586d7f5d3SJohn Marino     f.cyl = cyl;
4686d7f5d3SJohn Marino     f.transfer_rate = rate;
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino     f.fd_formb_secshift = secsize;
4986d7f5d3SJohn Marino     f.fd_formb_nsecs = secs;
5086d7f5d3SJohn Marino     f.fd_formb_gaplen = gaplen;
5186d7f5d3SJohn Marino     f.fd_formb_fillbyte = fill;
5286d7f5d3SJohn Marino     for(i = 0; i < secs; i++) {
5386d7f5d3SJohn Marino 	f.fd_formb_cylno(i) = cyl;
5486d7f5d3SJohn Marino 	f.fd_formb_headno(i) = head;
5586d7f5d3SJohn Marino 	f.fd_formb_secno(i) = il[i+1];
5686d7f5d3SJohn Marino 	f.fd_formb_secsize(i) = secsize;
5786d7f5d3SJohn Marino     }
5886d7f5d3SJohn Marino     return ioctl(fd, FD_FORM, (caddr_t)&f);
5986d7f5d3SJohn Marino }
6086d7f5d3SJohn Marino 
6186d7f5d3SJohn Marino static void
usage(void)6286d7f5d3SJohn Marino usage(void)
6386d7f5d3SJohn Marino {
6486d7f5d3SJohn Marino 	fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n");
6586d7f5d3SJohn Marino 	exit(2);
6686d7f5d3SJohn Marino }
6786d7f5d3SJohn Marino 
6886d7f5d3SJohn Marino int
main(int argc,char ** argv)6986d7f5d3SJohn Marino main(int argc, char **argv)
7086d7f5d3SJohn Marino {
7186d7f5d3SJohn Marino     int inputfd = -1, c, fdn = 0, i,j,fd;
7286d7f5d3SJohn Marino     int bpt, verbose=1, nbytes=0, track;
7386d7f5d3SJohn Marino     int interactive = 1, fdopts;
7486d7f5d3SJohn Marino     const char *device = "/dev/fd0";
7586d7f5d3SJohn Marino     char *trackbuf = NULL,*vrfybuf = NULL;
7686d7f5d3SJohn Marino     struct fd_type fdt;
7786d7f5d3SJohn Marino     FILE *tty;
7886d7f5d3SJohn Marino 
7986d7f5d3SJohn Marino     setbuf(stdout,0);
8086d7f5d3SJohn Marino     while((c = getopt(argc, argv, "d:f:vy")) != -1)
8186d7f5d3SJohn Marino 	    switch(c) {
8286d7f5d3SJohn Marino 	    case 'd':	/* Which drive */
8386d7f5d3SJohn Marino 		    device = optarg;
8486d7f5d3SJohn Marino 		    break;
8586d7f5d3SJohn Marino 
8686d7f5d3SJohn Marino 	    case 'f':	/* input file */
8786d7f5d3SJohn Marino 		    if (inputfd >= 0)
8886d7f5d3SJohn Marino 			    close(inputfd);
8986d7f5d3SJohn Marino 		    inputfd = open(optarg,O_RDONLY);
9086d7f5d3SJohn Marino 		    if (inputfd < 0)
9186d7f5d3SJohn Marino 			    err(1, "%s", optarg);
9286d7f5d3SJohn Marino 		    break;
9386d7f5d3SJohn Marino 
9486d7f5d3SJohn Marino 	    case 'v':  /* Toggle verbosity */
9586d7f5d3SJohn Marino 		    verbose = !verbose;
9686d7f5d3SJohn Marino 		    break;
9786d7f5d3SJohn Marino 
9886d7f5d3SJohn Marino 	    case 'y':  /* Don't confirm? */
9986d7f5d3SJohn Marino 		    interactive = 0;
10086d7f5d3SJohn Marino 		    break;
10186d7f5d3SJohn Marino 
10286d7f5d3SJohn Marino 	    case '?': default:
10386d7f5d3SJohn Marino 		    usage();
10486d7f5d3SJohn Marino 	    }
10586d7f5d3SJohn Marino 
10686d7f5d3SJohn Marino     if (inputfd < 0)
10786d7f5d3SJohn Marino 	inputfd = 0;
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino     if (!isatty(1))
11086d7f5d3SJohn Marino 	interactive = 0;
11186d7f5d3SJohn Marino 
11286d7f5d3SJohn Marino     if(optind < argc)
11386d7f5d3SJohn Marino 	    usage();
11486d7f5d3SJohn Marino 
11586d7f5d3SJohn Marino     tty = fopen(_PATH_TTY,"r+");
11686d7f5d3SJohn Marino     if(!tty)
11786d7f5d3SJohn Marino 	    err(1, _PATH_TTY);
11886d7f5d3SJohn Marino     setbuf(tty,0);
11986d7f5d3SJohn Marino 
12086d7f5d3SJohn Marino     for(j=1;j > 0;) {
12186d7f5d3SJohn Marino         fdn++;
12286d7f5d3SJohn Marino 	if (interactive) {
12386d7f5d3SJohn Marino 	    fprintf(tty,
12486d7f5d3SJohn Marino 		    "Please insert floppy #%d in drive %s and press return >",
12586d7f5d3SJohn Marino 		    fdn,device);
12686d7f5d3SJohn Marino 	    while(1) {
12786d7f5d3SJohn Marino 		i = getc(tty);
12886d7f5d3SJohn Marino 		if(i == '\n') break;
12986d7f5d3SJohn Marino 	    }
13086d7f5d3SJohn Marino 	}
13186d7f5d3SJohn Marino 
13286d7f5d3SJohn Marino 	if((fd = open(device, O_RDWR)) < 0)
13386d7f5d3SJohn Marino 	    err(1, "%s", device);
13486d7f5d3SJohn Marino 
13586d7f5d3SJohn Marino 	if(ioctl(fd, FD_GTYPE, &fdt) < 0)
13686d7f5d3SJohn Marino 	    errx(1, "not a floppy disk: %s", device);
13786d7f5d3SJohn Marino 	fdopts = FDOPT_NOERRLOG;
13886d7f5d3SJohn Marino 	if (ioctl(fd, FD_SOPTS, &fdopts) == -1)
13986d7f5d3SJohn Marino 		err(1, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)");
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino 	bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
14286d7f5d3SJohn Marino 	if(!trackbuf) {
14386d7f5d3SJohn Marino 	    trackbuf = malloc(bpt);
14486d7f5d3SJohn Marino 	    if(!trackbuf) err(1, "malloc failed");
14586d7f5d3SJohn Marino 	}
14686d7f5d3SJohn Marino 	if(!vrfybuf) {
14786d7f5d3SJohn Marino 	    vrfybuf = malloc(bpt);
14886d7f5d3SJohn Marino 	    if(!vrfybuf) err(1, "malloc failed");
14986d7f5d3SJohn Marino 	}
15086d7f5d3SJohn Marino 
15186d7f5d3SJohn Marino 	if(fdn == 1) {
15286d7f5d3SJohn Marino 	    if(verbose) {
15386d7f5d3SJohn Marino 		printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
15486d7f5d3SJohn Marino 		fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
15586d7f5d3SJohn Marino 		fdt.tracks*bpt*fdt.heads/1024);
15686d7f5d3SJohn Marino 
15786d7f5d3SJohn Marino 	    }
15886d7f5d3SJohn Marino 	    memset(trackbuf,0,bpt);
15986d7f5d3SJohn Marino 	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
16086d7f5d3SJohn Marino 		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
16186d7f5d3SJohn Marino 		    close(inputfd);
16286d7f5d3SJohn Marino 		    inputfd = -1;
16386d7f5d3SJohn Marino 		    break;
16486d7f5d3SJohn Marino 		}
16586d7f5d3SJohn Marino 		nbytes += i;
16686d7f5d3SJohn Marino 	    }
16786d7f5d3SJohn Marino 	}
16886d7f5d3SJohn Marino 	for (track = 0; track < fdt.tracks * fdt.heads; track++) {
16986d7f5d3SJohn Marino 	    if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
17086d7f5d3SJohn Marino 	    if(verbose) putc((j ? 'I':'Z'),stdout);
17186d7f5d3SJohn Marino 	    format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
17286d7f5d3SJohn Marino 		    fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
17386d7f5d3SJohn Marino 		    fdt.f_inter);
17486d7f5d3SJohn Marino 	    if(verbose) putc('F',stdout);
17586d7f5d3SJohn Marino 
17686d7f5d3SJohn Marino 	    if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
17786d7f5d3SJohn Marino 	    if (write (fd, trackbuf, bpt) != bpt) err(1, "write");
17886d7f5d3SJohn Marino 	    if(verbose) putc('W',stdout);
17986d7f5d3SJohn Marino 
18086d7f5d3SJohn Marino 	    if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
18186d7f5d3SJohn Marino 	    if (read (fd, vrfybuf, bpt) != bpt) err(1, "read");
18286d7f5d3SJohn Marino 	    if(verbose) putc('R',stdout);
18386d7f5d3SJohn Marino 
18486d7f5d3SJohn Marino 	    if (memcmp(trackbuf,vrfybuf,bpt)) err(1, "compare");
18586d7f5d3SJohn Marino 	    if(verbose) putc('C',stdout);
18686d7f5d3SJohn Marino 
18786d7f5d3SJohn Marino 	    memset(trackbuf,0,bpt);
18886d7f5d3SJohn Marino 	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
18986d7f5d3SJohn Marino 		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
19086d7f5d3SJohn Marino 		    close(inputfd);
19186d7f5d3SJohn Marino 		    inputfd = -1;
19286d7f5d3SJohn Marino 		    break;
19386d7f5d3SJohn Marino 		}
19486d7f5d3SJohn Marino 		nbytes += i;
19586d7f5d3SJohn Marino 	    }
19686d7f5d3SJohn Marino 	}
19786d7f5d3SJohn Marino 	close(fd);
19886d7f5d3SJohn Marino 	putc('\r',stdout);
19986d7f5d3SJohn Marino     }
20086d7f5d3SJohn Marino     if(verbose)
20186d7f5d3SJohn Marino 	printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
20286d7f5d3SJohn Marino     exit(0);
20386d7f5d3SJohn Marino }
204