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.