1/* Copyright 1999-2003,2007,2009 Alain Knaff. 2 * This file is part of mtools. 3 * 4 * Mtools is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * Mtools is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * mcat.c 18 * Same thing as cat /dev/fd0 or cat file >/dev/fd0 19 * Something, that isn't possible with floppyd anymore. 20 */ 21 22#include "sysincludes.h" 23#include "msdos.h" 24#include "mtools.h" 25#include "mainloop.h" 26#include "fsP.h" 27#include "xdf_io.h" 28#include "floppyd_io.h" 29#include "plain_io.h" 30 31static void usage(void) 32{ 33 fprintf(stderr, "Mtools version %s, dated %s\n", 34 mversion, mdate); 35 fprintf(stderr, "Usage: mcat [-V] [-w] device\n"); 36 fprintf(stderr, " -w write on device else read\n"); 37 exit(1); 38} 39 40#ifdef __CYGWIN__ 41#define BUF_SIZE 512 42#else 43#define BUF_SIZE 16000 44#endif 45 46static size_t bufLen(size_t blocksize, mt_size_t totalSize, mt_off_t address) 47{ 48 if(totalSize == 0) 49 return blocksize; 50 if(address + blocksize > totalSize) 51 return totalSize - address; 52 return blocksize; 53} 54 55void mcat(int argc, char **argv, int type) 56{ 57 struct device *dev; 58 struct device out_dev; 59 char drive, name[EXPAND_BUF]; 60 char errmsg[200]; 61 Stream_t *Stream; 62 char buf[BUF_SIZE]; 63 64 mt_off_t address = 0; 65 66 char mode = O_RDONLY; 67 int optindex = 1; 68 size_t len; 69 70 noPrivileges = 1; 71 72 if (argc < 2) { 73 usage(); 74 } 75 76 if (argv[1][0] == '-') { 77 if (argv[1][1] != 'w') { 78 usage(); 79 } 80 mode = O_WRONLY; 81 optindex++; 82 } 83 84 if (argc - optindex < 1) 85 usage(); 86 87 88 if (!argv[optindex][0] || argv[optindex][1] != ':' 89 || argv[optindex][2]) { 90 usage(); 91 } 92 93 drive = toupper(argv[optindex][0]); 94 95 /* check out a drive whose letter and parameters match */ 96 sprintf(errmsg, "Drive '%c:' not supported", drive); 97 Stream = NULL; 98 for (dev=devices; dev->name; dev++) { 99 FREE(&Stream); 100 if (dev->drive != drive) 101 continue; 102 out_dev = *dev; 103 expand(dev->name,name); 104#ifdef USING_NEW_VOLD 105 strcpy(name, getVoldName(dev, name)); 106#endif 107 108 Stream = 0; 109#ifdef USE_XDF 110 Stream = XdfOpen(&out_dev, name, mode, errmsg, 0); 111 if(Stream) 112 out_dev.use_2m = 0x7f; 113 114#endif 115 116#ifdef USE_FLOPPYD 117 if(!Stream) 118 Stream = FloppydOpen(&out_dev, dev, name, 119 mode, errmsg, 0, 1); 120#endif 121 122 123 if (!Stream) 124 Stream = SimpleFileOpen(&out_dev, dev, name, mode, 125 errmsg, 0, 1, 0); 126 127 if( !Stream) 128 continue; 129 break; 130 } 131 132 /* print error msg if needed */ 133 if ( dev->drive == 0 ){ 134 FREE(&Stream); 135 fprintf(stderr,"%s\n",errmsg); 136 exit(1); 137 } 138 139 140 if (mode == O_WRONLY) { 141 mt_size_t size=0; 142 size = out_dev.sectors * out_dev.heads * out_dev.tracks; 143 size *= 512; 144 while ((len = fread(buf, 1, 145 bufLen(BUF_SIZE, size, address), 146 stdin)) > 0) { 147 int r = WRITES(Stream, buf, address, len); 148 fprintf(stderr, "Wrote to %d\n", (int) address); 149 if(r < 0) 150 break; 151 address += len; 152 } 153 } else { 154 while ((len = READS(Stream, buf, address, BUF_SIZE)) > 0) { 155 fwrite(buf, 1, len, stdout); 156 address += len; 157 } 158 } 159 160 FREE(&Stream); 161 exit(0); 162} 163