xref: /aosp_15_r20/external/mtools/mcat.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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