[unix-pc.sources] fdread/fdwrite program for accessing "foreign" floppies on Unix PC

ditto@cbmvax.UUCP (Michael "Ford" Ditto) (01/10/89)

This is the source to my "fdread" and "fdwrite" commands (actually the
same program) which allow access to floppies of various formats and
without a partition table.  I have used it to transfer tar archives on
floppy between Unix PCs, Xenix PClones, and Regulus systems.

I think I posted a slightly earlier version of this a while back, but
this one is better.

					-=] Ford [=-

"The number of Unix installations	(In Real Life:  Mike Ditto)
has grown to 10, with more expected."	ford@kenobi.cts.com
- The Unix Programmer's Manual,		...!sdcsvax!crash!elgar!ford
  2nd Edition, June, 1972.		ditto@cbmvax.commodore.com

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	fd.doc
#	Makefile
#	fdwrite.c
# This archive created: Fri Jan  6 15:14:17 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'fd.doc'" '(1484 characters)'
if test -f 'fd.doc'
then
	echo shar: will not over-write existing file "'fd.doc'"
else
cat << \SHAR_EOF > 'fd.doc'
Here's my "fdread"/"fdwrite" program for the Unix PC.

The fdread/fdwrite program allows "raw" access to floppy disks,
including track 0, without requiring a volume header block (partition
table).  The default parameters are set up for "ibm" format floppy
disks, that is, double sided, 48 tracks per inch, double density, 9
sectors per track, 512 bytes per sector, for a total of 360K storage.
This is less storage than the normal Unix PC format, but it can be read
on IBM-pc-type machines, such as the ones that run Xenix.

The program operates by opening the floppy disk drive as standard
input (or output, in the case of fdwrite) and then "exec"ing whatever
program you wish to use.  The program you specify must do its reading
from standard input (or writing to standard output).  Examples of how
to arrange this with tar(1) are given below.

The program defaults to the parameters given above (48tpi, DSDD,
etc.), but they can individually be specified by paramters on the
command line.

Examples:

	To write a tar archive onto an IBM-formatted floppy:

		fdwrite /dev/rfp020 tar -cvf - foo bar baz

	And then to read it on Xenix:

		tar -xvf /dev/rfd048ds9

	To read it on Regulus:

		tar -xvf /dev/raw/fibm

	To read such a disk back into the Unix PC:

		fdread /dev/rfp020 tar -xvf -

	Note that tar must be given an archivename of "-" to indicate that
		standard {input,output} must be used.



Enjoy the program, and let me know if you have any suggestions or
improvements.
SHAR_EOF
if test 1484 -ne "`wc -c < 'fd.doc'`"
then
	echo shar: error transmitting "'fd.doc'" '(should have been 1484 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(74 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
D	= -O
CFLAGS	= $D

fdread : fdwrite
	rm -f fdread
	ln -f fdwrite fdread

SHAR_EOF
if test 74 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 74 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fdwrite.c'" '(2593 characters)'
if test -f 'fdwrite.c'
then
	echo shar: will not over-write existing file "'fdwrite.c'"
else
cat << \SHAR_EOF > 'fdwrite.c'
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/gdisk.h>
#include <sys/gdioctl.h>

extern char *strrchr();


char *progname;

void usage()
{
    fprintf(stderr,
	    "Usage: %s [-f flags] [-c cyls] [-h heads] [-s sectors]\n",
	    progname);
    fputs("              [-T sec/trk] [-C sec/cyl] <devname> <command>\n",
	  stderr);
    exit(-1);
}


main(argc, argv)
int argc;
char *argv[];
{
    int fd, mode, usefd;
    char buf[512];
    struct gdctl gdctl;
    char flags = 1;
    ushort cyls = 40;
    ushort heads = 2;
    ushort sectrk = 9;
    ushort seccyl = 18;
    ushort sectorsz = 512;

    progname = strrchr(argv[0], '/');
    if (!progname)
	progname = argv[0];
    else
	++progname;

    if (!strcmp(progname, "fdwrite"))
    {
	mode = O_RDWR;
	usefd = 1;
    }
    else
    {
	mode = O_RDONLY;
	usefd = 0;
    }

    while ( (++argv,--argc) && **argv=='-' && argv[0][1] )
    {
	register char c, *p;

	p = *argv+1;
	while (c = *p++) switch(c)
	{
	case 'c':
	    if (!(++argv,--argc)) goto badflag;
	    cyls = atoi(*argv);
	    break;
	case 'h':
	    if (!(++argv,--argc)) goto badflag;
	    heads = atoi(*argv);
	    seccyl = heads * sectrk;
	    break;
	case 's':
	    if (!(++argv,--argc)) goto badflag;
	    sectrk = atoi(*argv);
	    seccyl = heads * sectrk;
	    break;
	case 'b':
	    if (!(++argv,--argc)) goto badflag;
	    sectorsz = atoi(*argv);
	    break;
	case 'T':
	    if (!(++argv,--argc)) goto badflag;
	    sectrk = atoi(*argv);
	    break;
	case 'C':
	    if (!(++argv,--argc)) goto badflag;
	    seccyl = atoi(*argv);
	    break;
	case 'f':
	    if (!(++argv,--argc)) goto badflag;
	    flags = atoi(*argv);
	    break;

	default:
	badflag:
	    fprintf(stderr, "%s: bad flag `-%c'\n", progname, c);
	usage();
	}
    }

    if (argc<2)
	usage();

    fd = open(*argv, mode);
    if (fd<0)
    {
	sprintf(buf, "%s: can't open %s", progname, *argv);
	perror(buf);
	return -1;
    }

    if (ioctl(fd, GDGETA, &gdctl))
    {
	sprintf(buf, "%s: can't ioctl GDGETA", progname);
	perror(buf);
	return -1;
    }

    gdctl.status |= PHYS_ADDR;
    gdctl.params.cyls = cyls;
    gdctl.params.heads = heads;
    gdctl.params.psectrk = sectrk;
    gdctl.params.pseccyl = seccyl;
    gdctl.params.sectorsz = sectorsz;
    gdctl.params.flags = flags;

    if (ioctl(fd, GDSETA, &gdctl))
    {
	sprintf(buf, "%s: can't ioctl GDSETA", progname);
	perror(buf);
	return -1;
    }

    close(usefd);
    dup(fd);
    close(fd);

    execvp(argv[1], argv+1);

    sprintf(buf, "%s: can't exec %s", progname, argv[1]);
    perror(buf);
    return -1;
}
SHAR_EOF
if test 2593 -ne "`wc -c < 'fdwrite.c'`"
then
	echo shar: error transmitting "'fdwrite.c'" '(should have been 2593 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
					-=] Ford [=-

"The number of Unix installations	(In Real Life:  Mike Ditto)
has grown to 10, with more expected."	ford@kenobi.cts.com
- The Unix Programmer's Manual,		...!sdcsvax!crash!elgar!ford
  2nd Edition, June, 1972.		ditto@cbmvax.commodore.com

mark@cogent.UUCP (Captain Neptune) (01/11/89)

In article <5652@cbmvax.UUCP> ford@kenobi.commodore.com (Mike "Ford" Ditto) writes:
>This is the source to my "fdread" and "fdwrite" commands (actually the
>same program) which allow access to floppies of various formats and
>without a partition table.  I have used it to transfer tar archives on
>floppy between Unix PCs, Xenix PClones, and Regulus systems.

Sounds good to me, but tell me this?  What can these programs do that
could not be achieved via the "dd" command?  This is not a criticism,
just a question.
-- 
Mark Steven Jeghers                               "No reward for resistance,
Cogent Software Solutions                          no assistance,
...pacbell!cogent!mark                             no applause..."
...uunet!lll-winken!cogent!mark                                   Neil Peart