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