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