A small program, which can take a file of any size, format, write and verify
it onto a bunch of floppies in a semi-intelligent way. Useful for things like: tar cf - . | gzip -9 | fdwrite -d /dev/rfd0.1720 -v Where it will keep asking for floppies until tar is done.
This commit is contained in:
parent
9d8044d0d9
commit
b5173cbeea
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/phk/; revision=2849
16
usr.sbin/fdwrite/Makefile
Normal file
16
usr.sbin/fdwrite/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# ----------------------------------------------------------------------------
|
||||
# "THE BEER-WARE LICENSE" (Revision 42):
|
||||
# <phk@login.dkuug.dk> 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
|
||||
# ----------------------------------------------------------------------------
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
#
|
||||
|
||||
PROG = fdwrite
|
||||
CFLAGS+= -Wall -I${DESTDIR}/sys
|
||||
|
||||
.include <bsd.prog.mk>
|
117
usr.sbin/fdwrite/fdwrite.1
Normal file
117
usr.sbin/fdwrite/fdwrite.1
Normal file
@ -0,0 +1,117 @@
|
||||
.\"
|
||||
.\" ----------------------------------------------------------------------------
|
||||
.\" "THE BEER-WARE LICENSE" (Revision 42):
|
||||
.\" <phk@login.dkuug.dk> 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
|
||||
.\" ----------------------------------------------------------------------------
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\"
|
||||
.Dd September 16, 1993
|
||||
.Os FreeBSD
|
||||
.Dt FDWRITE 1
|
||||
.Sh NAME
|
||||
.Nm fdwrite
|
||||
.Nd format and write floppy disks
|
||||
.Sh SYNOPSIS
|
||||
.Nm fdwrite
|
||||
.Bq Fl v
|
||||
.Bq Fl f Ar inputfile
|
||||
.Bq Fl d Ar device
|
||||
.Sh DESCRIPTION
|
||||
.Nm Fdwrite
|
||||
formats and writes one and more floppy disks.
|
||||
Any floppy disk device capable of formatting can be used.
|
||||
|
||||
.Nm Fdwrite
|
||||
will ask the user
|
||||
.Pq on /dev/tty
|
||||
to insert a new floppy and press return.
|
||||
The device will then be opened, and queried for it's paramters,
|
||||
then each track will be formatted, written with data from the
|
||||
.Ar inputfile ,
|
||||
read back and compared.
|
||||
When the floppy disk if filled, the process is repeated, with the next disk.
|
||||
This continues until the program is interrupted or EOF is encountered on the
|
||||
.Ar inputfile .
|
||||
|
||||
The options are as follows:
|
||||
.Bl -tag -width 10n -offset indent
|
||||
.It Fl v
|
||||
toggles verbosity on stdout.
|
||||
Default is ``on''.
|
||||
After
|
||||
.Ar device
|
||||
is opened first time the format will be printed.
|
||||
During operation progress will be reported with the number of tracks
|
||||
remaining on the current floppy disk, and the letters I, Z, F, W,
|
||||
R and C, which indicates completion of Input, Zero-fill, Format
|
||||
Write, Read and Compare of current track respectively.
|
||||
.It Fl f Ar inputfile
|
||||
Input file to read. If none is given, stdin is assumed.
|
||||
.It Fl d Ar device
|
||||
The name of the floppy device to write to. Default is ``/dev/rfd0''.
|
||||
.El
|
||||
|
||||
.Nm Fdwrite
|
||||
actually closes the
|
||||
.Ar device
|
||||
while it waits for the user to press return,
|
||||
it is thus quite possible to use the drive for other purposes at this
|
||||
time and later resume writing with the next floppy.
|
||||
|
||||
The parameters returned from
|
||||
.Ar device
|
||||
are used for formatting.
|
||||
If custom formatting is needed, please use
|
||||
.Xr fdformat 1
|
||||
instead.
|
||||
|
||||
.Sh EXAMPLE
|
||||
.Nm Fdwrite
|
||||
was planned as a tool to make life easier when writing a set of floppies,
|
||||
one such use could be to write a tar-archive:
|
||||
|
||||
.ce 1
|
||||
tar cf - . | gzip -9 | fdwrite -d /dev/rfd0.1720 -v
|
||||
|
||||
The main difference from using
|
||||
.Xr tar 1 's
|
||||
multivolume facility is of course the formatting of the floppies, which
|
||||
here is done on the fly,
|
||||
thus reducing the amount of work for the floppy-jockey.
|
||||
|
||||
.Sh SEE ALSO
|
||||
.Xr fdformat 1 .
|
||||
.Sh HISTORY
|
||||
.Nm Fdwrite
|
||||
was written while waiting for ``make world'' to complete.
|
||||
Some of the code was taken from
|
||||
.Xr fdformat 1 .
|
||||
.Sh AUTHOR
|
||||
The program has been contributed by
|
||||
Poul-Henning Kamp <phk@login.dknet.dk>
|
||||
.Sh BUGS
|
||||
Diagnostics are less than complete at present.
|
||||
|
||||
If a floppy is sick, and the
|
||||
.Ar inputfile
|
||||
is seekable, it should ask the user to frisbee the disk, insert
|
||||
another, and rewind to the right spot and continue.
|
||||
|
||||
This concept could be extended to cover non-seekable input also
|
||||
by employing a temporary file .
|
||||
|
||||
An option (defaulting to zero) should allow the user to ask for
|
||||
retries in case of failure.
|
||||
|
||||
At present a suitable tool for reading back a multivolume set
|
||||
of floppies is missing.
|
||||
Programs like
|
||||
.Xr tar 1
|
||||
for instance, will do the job, if the data has not been compressed.
|
||||
One can always trust
|
||||
.Xr dd 1
|
||||
to help out in this situation of course
|
208
usr.sbin/fdwrite/fdwrite.c
Normal file
208
usr.sbin/fdwrite/fdwrite.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <phk@login.dkuug.dk> 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
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <machine/ioctl_fd.h>
|
||||
#include <i386/isa/fdreg.h> /* XXX should be in <machine> dir */
|
||||
|
||||
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 ()
|
||||
{
|
||||
printf("Usage:\n\tfdwrite [-v] [-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;
|
||||
char *device= "/dev/rfd0", *trackbuf = 0,*vrfybuf = 0;
|
||||
struct fd_type fdt;
|
||||
FILE *tty;
|
||||
|
||||
setbuf(stdout,0);
|
||||
while((c = getopt(argc, argv, "d:s:f:v")) != -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) {
|
||||
perror(optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v': /* Toggle verbosity */
|
||||
verbose = !verbose;
|
||||
break;
|
||||
|
||||
case '?': default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (inputfd < 0)
|
||||
inputfd = 0;
|
||||
|
||||
if(optind < argc)
|
||||
usage();
|
||||
|
||||
tty = fopen("/dev/tty","r+");
|
||||
if(!tty) {
|
||||
perror("/dev/tty");
|
||||
exit(1);
|
||||
}
|
||||
setbuf(tty,0);
|
||||
|
||||
for(j=1;j > 0;) {
|
||||
fdn++;
|
||||
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) {
|
||||
perror(device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(ioctl(fd, FD_GTYPE, &fdt) < 0) {
|
||||
fprintf(stderr, "fdformat: not a floppy disk: %s\n", device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
|
||||
if(!trackbuf) {
|
||||
trackbuf = malloc(bpt);
|
||||
if(!trackbuf) { perror("malloc"); exit(1); }
|
||||
}
|
||||
if(!vrfybuf) {
|
||||
vrfybuf = malloc(bpt);
|
||||
if(!vrfybuf) { perror("malloc"); exit(1); }
|
||||
}
|
||||
|
||||
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) {
|
||||
perror("lseek");
|
||||
exit (1);
|
||||
}
|
||||
if (write (fd, trackbuf, bpt) != bpt) {
|
||||
perror("write");
|
||||
exit (1);
|
||||
}
|
||||
if(verbose) putc('W',stdout);
|
||||
|
||||
if (lseek (fd, (long) track*bpt, 0) < 0) {
|
||||
perror("lseek");
|
||||
exit (1);
|
||||
}
|
||||
if (read (fd, vrfybuf, bpt) != bpt) {
|
||||
perror("read");
|
||||
exit (1);
|
||||
}
|
||||
if(verbose) putc('R',stdout);
|
||||
|
||||
if (memcmp(trackbuf,vrfybuf,bpt)) {
|
||||
perror("compare");
|
||||
exit (1);
|
||||
}
|
||||
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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user