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
31 static void usage(void) NORETURN;
usage(void)32 static void usage(void)
33 {
34 fprintf(stderr, "Mtools version %s, dated %s\n",
35 mversion, mdate);
36 fprintf(stderr, "Usage: mcat [-V] [-w] device\n");
37 fprintf(stderr, " -w write on device else read\n");
38 exit(1);
39 }
40
41 #ifdef __CYGWIN__
42 #define BUF_SIZE 512u
43 #else
44 #define BUF_SIZE 16000u
45 #endif
46
bufLen(size_t blocksize,mt_size_t totalSize,mt_off_t address)47 static size_t bufLen(size_t blocksize, mt_size_t totalSize, mt_off_t address)
48 {
49 if(totalSize == 0)
50 return blocksize;
51 if(address + blocksize > totalSize)
52 return totalSize - address;
53 return blocksize;
54 }
55
56 void mcat(int argc, char **argv, int type UNUSEDP) NORETURN;
mcat(int argc,char ** argv,int type UNUSEDP)57 void mcat(int argc, char **argv, int type UNUSEDP)
58 {
59 struct device *dev;
60 struct device out_dev;
61 char drive, name[EXPAND_BUF];
62 char errmsg[200];
63 Stream_t *Stream;
64 char buf[BUF_SIZE];
65
66 mt_off_t address = 0;
67
68 char mode = O_RDONLY;
69 int optindex = 1;
70 size_t len;
71
72 noPrivileges = 1;
73
74 if (argc < 2) {
75 usage();
76 }
77
78 if (argv[1][0] == '-') {
79 if (argv[1][1] != 'w') {
80 usage();
81 }
82 mode = O_WRONLY;
83 optindex++;
84 }
85
86 if (argc - optindex < 1)
87 usage();
88
89
90 if (!argv[optindex][0] || argv[optindex][1] != ':'
91 || argv[optindex][2]) {
92 usage();
93 }
94
95 drive = ch_toupper(argv[optindex][0]);
96
97 /* check out a drive whose letter and parameters match */
98 sprintf(errmsg, "Drive '%c:' not supported", drive);
99 Stream = NULL;
100 for (dev=devices; dev->name; dev++) {
101 FREE(&Stream);
102 if (dev->drive != drive)
103 continue;
104 out_dev = *dev;
105 expand(dev->name,name);
106 #ifdef USING_NEW_VOLD
107 strcpy(name, getVoldName(dev, name));
108 #endif
109
110 Stream = 0;
111 #ifdef USE_XDF
112 Stream = XdfOpen(&out_dev, name, mode, errmsg, 0);
113 if(Stream)
114 out_dev.use_2m = 0x7f;
115
116 #endif
117
118 #ifdef USE_FLOPPYD
119 if(!Stream)
120 Stream = FloppydOpen(&out_dev, name,
121 mode, errmsg, NULL);
122 #endif
123
124
125 if (!Stream)
126 Stream = SimpleFileOpen(&out_dev, dev, name, mode,
127 errmsg, 0, 1, 0);
128
129 if( !Stream)
130 continue;
131 break;
132 }
133
134 /* print error msg if needed */
135 if ( dev->drive == 0 ){
136 FREE(&Stream);
137 fprintf(stderr,"%s\n",errmsg);
138 exit(1);
139 }
140
141
142 if (mode == O_WRONLY) {
143 mt_size_t size=0;
144 size = out_dev.sectors * out_dev.heads * out_dev.tracks;
145 size *= 512;
146 while ((len = fread(buf, 1,
147 bufLen(BUF_SIZE, size, address),
148 stdin)) > 0) {
149 int r = WRITES(Stream, buf, address, len);
150 fprintf(stderr, "Wrote to %d\n", (int) address);
151 if(r < 0)
152 break;
153 address += len;
154 }
155 } else {
156 while ((len = READS(Stream, buf, address, BUF_SIZE)) > 0) {
157 fwrite(buf, 1, len, stdout);
158 address += len;
159 }
160 }
161
162 FREE(&Stream);
163 exit(0);
164 }
165