This is rawdisk.c in view mode; [Download] [Up]
/*
* rawdisk: spew stdin to raw disk(s) or raw disk(s) to stdout
* for more details, see acompanying README file
*
* Copyright (C) 1991, Richard O'Neill.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
#include <c.h>
#include <stdio.h>
#include <stdlib.h>
#include <varargs.h>
#include <sys/errno.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <nextdev/disk.h>
const char *programname = "rawdisk";
/*
* Emergency exiting...
*/
struct suicide_handler_info {};
typedef void ((*suicide_fun)(struct suicide_handler_info *, va_list args));
struct suicide_handler {
suicide_fun action;
struct suicide_handler_info info;
};
struct suicide_handler_list {
struct suicide_handler *handler;
struct suicide_handler_list *next;
};
void std_suicide (struct suicide_handler_info *info, va_list args)
{
char *format;
format = va_arg(args, char *);
fprintf(stderr,"%s: ",programname);
vfprintf(stderr,format,args);
if (errno)
fprintf(stderr," (%s)\n",strerror(errno));
else
fputc('\n',stderr);
}
struct suicide_handler
std_suicide_handler = {std_suicide, {}};
struct suicide_handler_list
initial_suicide_handler_list = {&std_suicide_handler, NULL};
struct suicide_handler_list
*suicide_handler_list_ptr = &initial_suicide_handler_list;
static int exitcode;
void suicide (va_alist)
va_dcl
{
struct suicide_handler_list *cell_ptr;
va_list args;
va_start(args);
exitcode = va_arg(args, int);
cell_ptr = suicide_handler_list_ptr;
while (cell_ptr != NULL) {
(cell_ptr->handler->action)(&(cell_ptr->handler->info),args);
cell_ptr = cell_ptr->next;
}
va_end(args);
/* if (exitcode != 0xdeafbabe) */
exit(exitcode);
}
void push_suicide_handler (struct suicide_handler *candidate)
{
struct suicide_handler_list *cell_ptr;
cell_ptr = (struct suicide_handler_list *) malloc(sizeof(struct suicide_handler_list));
if (cell_ptr == NULL)
suicide(4, "Can't install error handler");
cell_ptr->handler = candidate;
cell_ptr->next = suicide_handler_list_ptr;
suicide_handler_list_ptr = cell_ptr;
}
struct suicide_handler *pop_suicide_handler()
{
struct suicide_handler_list *cell_ptr;
struct suicide_handler *handler;
cell_ptr = suicide_handler_list_ptr;
suicide_handler_list_ptr = cell_ptr->next;
handler = cell_ptr->handler;
free(cell_ptr);
return handler;
}
struct diskopen_suicide_handler_info {
int disk_fd;
};
struct diskopen_suicide_handler {
suicide_fun action;
struct diskopen_suicide_handler_info info;
};
void diskopen_suicide(struct suicide_handler_info *info, va_list args)
{
closedisk(((struct diskopen_suicide_handler_info *) info)->disk_fd);
}
void push_diskopen_suicide_handler(int disk_fd)
{
struct diskopen_suicide_handler *handler;
handler = (struct diskopen_suicide_handler *) malloc(sizeof(struct diskopen_suicide_handler));
if (handler == NULL) {
_closedisk(disk_fd);
suicide(8,"Can't install error handler");
}
handler->action = diskopen_suicide;
handler->info.disk_fd = disk_fd;
push_suicide_handler((struct suicide_handler *) handler);
}
void pop_diskopen_suicide_handler()
{
free(pop_suicide_handler());
}
int opendisk (flags)
int flags;
{
int ctrl_fd, disk_fd;
int freevol;
static char rawdevice[] = "/dev/rfd0a";
struct drive_info drive_info;
const char *control_dev = "/dev/fdc0";
ctrl_fd = open (control_dev, O_RDONLY, 0);
if (ctrl_fd < 0)
suicide(4, "Can't open disk controller, %s", control_dev);
if (ioctl(ctrl_fd, DKIOCGFREEVOL, &freevol))
suicide(8, "Can't find free volume, %s", control_dev);
rawdevice[8] += freevol;
disk_fd = open (rawdevice, flags, 0);
close(ctrl_fd);
if (disk_fd < 0)
suicide(2,"Can't open raw disk, %s", rawdevice);
push_diskopen_suicide_handler(disk_fd);
return disk_fd;
}
int _closedisk (disk_fd)
int disk_fd;
{
if (ioctl(disk_fd,DKIOCEJECT,NULL))
suicide(8, "Can't eject disk");
close(disk_fd);
}
int closedisk (disk_fd)
int disk_fd;
{
pop_diskopen_suicide_handler();
_closedisk(disk_fd);
}
int sectorsize(disk_fd)
int disk_fd;
{
struct drive_info drive_info;
if (ioctl(disk_fd,DKIOCINFO,&drive_info))
suicide(8, "Can't determine sector size");
return drive_info.di_devblklen;
}
#define CHUNKSIZE 65536
int readdisk()
{
int in_fd;
const int out_fd = 1;
bool usingthisdisk, demand = true;
int blocksize, chunksize, buffersize;
void *buffer, *buffer_posn;
int in_count, out_count, buffer_count;
buffersize = 0;
while(demand) {
usingthisdisk = true;
in_fd = opendisk(O_RDONLY);
blocksize = sectorsize(in_fd);
chunksize = (CHUNKSIZE / blocksize) * blocksize;
if (buffersize < chunksize) {
buffersize = chunksize;
buffer = alloca(buffersize);
}
while(usingthisdisk) {
in_count = read(in_fd,buffer,chunksize);
if (in_count < 0)
suicide(4,"Unexpected error reading floppy");
else if (in_count == 0)
usingthisdisk = false;
else {
buffer_posn = buffer;
buffer_count = in_count;
do {
out_count = write(out_fd,buffer_posn,buffer_count);
buffer_posn += out_count;
buffer_count -= out_count;
} while((buffer_count > 0) && (out_count > 0));
if (out_count < 0) {
if (errno == EPIPE) {
usingthisdisk = false;
demand = false;
}
else
suicide(4,"Unexpected error writing to stdout");
} else if (out_count == 0)
suicide(8,"Strangeness writing to stdout");
}
}
closedisk(in_fd);
}
}
int writedisk()
{
const int in_fd = 0;
int out_fd;
bool usingthisdisk, roundagain, demand = true;
int blocksize, chunksize, buffersize;
void *buffer, *buffer_posn;
int in_count, out_count, buffer_count;
buffersize = 0;
buffer_count = 0;
while(demand || roundagain) {
usingthisdisk = true;
roundagain = false;
out_fd = opendisk(O_WRONLY);
blocksize = sectorsize(out_fd);
chunksize = (CHUNKSIZE / blocksize) * blocksize;
if (buffersize < chunksize) {
buffersize = chunksize;
buffer = alloca(buffersize);
}
while(usingthisdisk) {
if (buffer_count == 0) {
buffer_posn = buffer;
do {
in_count = read(in_fd,buffer_posn,chunksize);
buffer_posn += in_count;
buffer_count += in_count;
} while((buffer_count % blocksize) && (in_count > 0));
if (in_count < 0)
suicide(4,"Unexpected error reading stdin");
else if (in_count == 0) {
if (buffer_count % blocksize)
buffer_count = (buffer_count / blocksize + 1) * blocksize;
usingthisdisk = false;
demand = false;
}
buffer_posn = buffer;
}
if (buffer_count > 0) {
out_count = write(out_fd,buffer_posn,buffer_count);
if (out_count < 0)
suicide(2,"Unexpected error writing to disk");
else if (out_count == 0) {
usingthisdisk = false;
roundagain = true;
}
else {
buffer_posn += out_count;
buffer_count -= out_count;
}
}
}
closedisk(out_fd);
}
}
void interupt()
{
suicide(2,"Transfer aborted by user");
}
main (argc, argv)
int argc;
char * argv[];
{
int opt;
bool opterr = false;
extern int optind;
extern char *optarg;
enum {Read, Write, Undefined} operation = Undefined;
int disk_fd;
struct drive_info drive_info;
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, interupt);
while ((opt = getopt(argc, argv, "rw")) != EOF)
switch (opt) {
case 'r':
if (operation == Undefined)
operation = Read;
else
opterr = true;
break;
case 'w':
if (operation == Undefined)
operation = Write;
else
opterr = true;
break;
case '?':
default:
opterr = true;
break;
}
if (opterr || (operation == Undefined)) {
fprintf(stderr,"Usage:\t%s -r\n\t%s -w\n",argv[0],argv[0]);
exit(1);
}
switch(operation) {
case Read:
readdisk();
break;
case Write:
writedisk();
break;
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.