1 /* Copyright 1999-2003,2007,2009 Alain Knaff.
2 * This file is part of mtools.
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.
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.
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/>.
18 * Same thing as cat /dev/fd0 or cat file >/dev/fd0
19 * Something, that isn't possible with floppyd anymore.
22 #include "sysincludes.h"
24 #include "open_image.h"
26 static void usage(void) NORETURN;
27 static void usage(void)
29 fprintf(stderr, "Mtools version %s, dated %s\n",
31 fprintf(stderr, "Usage: mcat [-V] [-w] device\n");
32 fprintf(stderr, " -w write on device else read\n");
39 #define BUF_SIZE 16000u
42 static size_t bufLen(size_t blocksize, mt_off_t totalSize, mt_off_t address)
46 if((mt_off_t) blocksize > totalSize - address)
47 return (size_t) (totalSize - address);
51 void mcat(int argc, char **argv, int type UNUSEDP) NORETURN;
52 void mcat(int argc, char **argv, int type UNUSEDP)
55 struct device out_dev;
56 char drive, name[EXPAND_BUF];
73 while ((c = getopt(argc,argv, "wi:"))!= EOF) {
79 set_cmd_line_image(optarg);
86 if (argc - optind > 1)
88 if(argc - optind == 1) {
89 if(!argv[optind][0] || argv[optind][1] != ':')
91 drive = ch_toupper(argv[argc -1][0]);
93 drive = get_default_drive();
96 /* check out a drive whose letter and parameters match */
97 sprintf(errmsg, "Drive '%c:' not supported", drive);
99 for (dev=devices; dev->name; dev++) {
101 if (dev->drive != drive)
104 expand(dev->name,name);
105 #ifdef USING_NEW_VOLD
106 strcpy(name, getVoldName(dev, name));
109 Stream = OpenImage(&out_dev, dev, name, mode,
110 errmsg, ALWAYS_GET_GEOMETRY, mode, &maxSize,
117 /* print error msg if needed */
118 if ( dev->drive == 0 )
121 if (mode == O_WRONLY) {
124 if(chs_to_totsectors(&out_dev, errmsg) < 0 ||
125 check_if_sectors_fit(out_dev.tot_sectors,
126 maxSize, 512, errmsg))
128 size = 512 * (mt_off_t) out_dev.tot_sectors;
129 while ((len = fread(buf, 1,
130 bufLen(BUF_SIZE, size, address),
132 ssize_t r = PWRITES(Stream, buf, address, len);
133 fprintf(stderr, "Wrote to %d\n", (int) address);
140 while ((len = PREADS(Stream, buf, address, BUF_SIZE)) > 0) {
141 fwrite(buf, 1, (size_t) len, stdout);
142 address += (size_t) len;
150 fprintf(stderr,"%s\n",errmsg);