summaryrefslogtreecommitdiffstats
path: root/usr.sbin/fdwrite/fdwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/fdwrite/fdwrite.c')
-rw-r--r--usr.sbin/fdwrite/fdwrite.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/usr.sbin/fdwrite/fdwrite.c b/usr.sbin/fdwrite/fdwrite.c
new file mode 100644
index 0000000..8c953a6
--- /dev/null
+++ b/usr.sbin/fdwrite/fdwrite.c
@@ -0,0 +1,196 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $FreeBSD$
+ *
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/fdcio.h>
+
+static int
+format_track(int fd, int cyl, int secs, int head, int rate,
+ int gaplen, int secsize, int fill, int interleave)
+{
+ struct fd_formb f;
+ register int i,j;
+ int il[100];
+
+ memset(il,0,sizeof il);
+ for(j = 0, i = 1; i <= secs; i++) {
+ while(il[(j%secs)+1]) j++;
+ il[(j%secs)+1] = i;
+ j += interleave;
+ }
+
+ f.format_version = FD_FORMAT_VERSION;
+ f.head = head;
+ f.cyl = cyl;
+ f.transfer_rate = rate;
+
+ f.fd_formb_secshift = secsize;
+ f.fd_formb_nsecs = secs;
+ f.fd_formb_gaplen = gaplen;
+ f.fd_formb_fillbyte = fill;
+ for(i = 0; i < secs; i++) {
+ f.fd_formb_cylno(i) = cyl;
+ f.fd_formb_headno(i) = head;
+ f.fd_formb_secno(i) = il[i+1];
+ f.fd_formb_secsize(i) = secsize;
+ }
+ return ioctl(fd, FD_FORM, (caddr_t)&f);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n");
+ exit(2);
+}
+
+int
+main(int argc, char **argv)
+{
+ int inputfd = -1, c, fdn = 0, i,j,fd;
+ int bpt, verbose=1, nbytes=0, track;
+ int interactive = 1;
+ const char *device= "/dev/fd0";
+ char *trackbuf = 0,*vrfybuf = 0;
+ struct fd_type fdt;
+ FILE *tty;
+
+ setbuf(stdout,0);
+ while((c = getopt(argc, argv, "d:f:vy")) != -1)
+ switch(c) {
+ case 'd': /* Which drive */
+ device = optarg;
+ break;
+
+ case 'f': /* input file */
+ if (inputfd >= 0)
+ close(inputfd);
+ inputfd = open(optarg,O_RDONLY);
+ if (inputfd < 0)
+ err(1, "%s", optarg);
+ break;
+
+ case 'v': /* Toggle verbosity */
+ verbose = !verbose;
+ break;
+
+ case 'y': /* Don't confirm? */
+ interactive = 0;
+ break;
+
+ case '?': default:
+ usage();
+ }
+
+ if (inputfd < 0)
+ inputfd = 0;
+
+ if (!isatty(1))
+ interactive = 0;
+
+ if(optind < argc)
+ usage();
+
+ tty = fopen(_PATH_TTY,"r+");
+ if(!tty)
+ err(1, _PATH_TTY);
+ setbuf(tty,0);
+
+ for(j=1;j > 0;) {
+ fdn++;
+ if (interactive) {
+ fprintf(tty,
+ "Please insert floppy #%d in drive %s and press return >",
+ fdn,device);
+ while(1) {
+ i = getc(tty);
+ if(i == '\n') break;
+ }
+ }
+
+ if((fd = open(device, O_RDWR)) < 0)
+ err(1, "%s", device);
+
+ if(ioctl(fd, FD_GTYPE, &fdt) < 0)
+ errx(1, "not a floppy disk: %s", device);
+
+ bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
+ if(!trackbuf) {
+ trackbuf = malloc(bpt);
+ if(!trackbuf) errx(1, "malloc");
+ }
+ if(!vrfybuf) {
+ vrfybuf = malloc(bpt);
+ if(!vrfybuf) errx(1, "malloc");
+ }
+
+ if(fdn == 1) {
+ if(verbose) {
+ printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
+ fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
+ fdt.tracks*bpt*fdt.heads/1024);
+
+ }
+ memset(trackbuf,0,bpt);
+ for(j=0;inputfd >= 0 && j<bpt;j+=i) {
+ if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
+ close(inputfd);
+ inputfd = -1;
+ break;
+ }
+ nbytes += i;
+ }
+ }
+ for (track = 0; track < fdt.tracks * fdt.heads; track++) {
+ if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
+ if(verbose) putc((j ? 'I':'Z'),stdout);
+ format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
+ fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
+ fdt.f_inter);
+ if(verbose) putc('F',stdout);
+
+ if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
+ if (write (fd, trackbuf, bpt) != bpt) err(1, "write");
+ if(verbose) putc('W',stdout);
+
+ if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
+ if (read (fd, vrfybuf, bpt) != bpt) err(1, "read");
+ if(verbose) putc('R',stdout);
+
+ if (memcmp(trackbuf,vrfybuf,bpt)) err(1, "compare");
+ if(verbose) putc('C',stdout);
+
+ memset(trackbuf,0,bpt);
+ for(j=0;inputfd >= 0 && j<bpt;j+=i) {
+ if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
+ close(inputfd);
+ inputfd = -1;
+ break;
+ }
+ nbytes += i;
+ }
+ }
+ close(fd);
+ putc('\r',stdout);
+ }
+ if(verbose)
+ printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
+ exit(0);
+}
OpenPOWER on IntegriCloud