blob: c0633e648fe59a9d5e96e8ed4dc69247d669f14d [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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"
Yi Kong39bbd962022-01-09 19:41:38 +080026#include "open_image.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080027
28static void usage(void) NORETURN;
Yi Kong39bbd962022-01-09 19:41:38 +080029static void usage(void)
Alistair Delvabeaee832021-02-24 11:27:23 -080030{
Yi Kong39bbd962022-01-09 19:41:38 +080031 fprintf(stderr, "Mtools version %s, dated %s\n",
Alistair Delvabeaee832021-02-24 11:27:23 -080032 mversion, mdate);
33 fprintf(stderr, "Usage: mcat [-V] [-w] device\n");
34 fprintf(stderr, " -w write on device else read\n");
35 exit(1);
36}
37
38#ifdef __CYGWIN__
39#define BUF_SIZE 512u
40#else
41#define BUF_SIZE 16000u
42#endif
43
Yi Kong39bbd962022-01-09 19:41:38 +080044static size_t bufLen(size_t blocksize, mt_off_t totalSize, mt_off_t address)
Alistair Delvabeaee832021-02-24 11:27:23 -080045{
46 if(totalSize == 0)
47 return blocksize;
Yi Kong39bbd962022-01-09 19:41:38 +080048 if((mt_off_t) blocksize > totalSize - address)
49 return (size_t) (totalSize - address);
Alistair Delvabeaee832021-02-24 11:27:23 -080050 return blocksize;
51}
52
53void mcat(int argc, char **argv, int type UNUSEDP) NORETURN;
54void mcat(int argc, char **argv, int type UNUSEDP)
55{
56 struct device *dev;
57 struct device out_dev;
58 char drive, name[EXPAND_BUF];
59 char errmsg[200];
60 Stream_t *Stream;
61 char buf[BUF_SIZE];
62
63 mt_off_t address = 0;
Yi Kong39bbd962022-01-09 19:41:38 +080064 mt_off_t maxSize = 0;
Alistair Delvabeaee832021-02-24 11:27:23 -080065
66 char mode = O_RDONLY;
Yi Kong39bbd962022-01-09 19:41:38 +080067 int c;
Alistair Delvabeaee832021-02-24 11:27:23 -080068
69 noPrivileges = 1;
70
71 if (argc < 2) {
72 usage();
73 }
74
Yi Kong39bbd962022-01-09 19:41:38 +080075 while ((c = getopt(argc,argv, "wi:"))!= EOF) {
76 switch (c) {
77 case 'w':
78 mode = O_WRONLY;
79 break;
80 case 'i':
81 set_cmd_line_image(optarg);
82 break;
83 default:
Alistair Delvabeaee832021-02-24 11:27:23 -080084 usage();
85 }
Alistair Delvabeaee832021-02-24 11:27:23 -080086 }
87
Yi Kong39bbd962022-01-09 19:41:38 +080088 if (argc - optind > 1)
Alistair Delvabeaee832021-02-24 11:27:23 -080089 usage();
Yi Kong39bbd962022-01-09 19:41:38 +080090 if(argc - optind == 1) {
91 if(!argv[optind][0] || argv[optind][1] != ':')
92 usage();
93 drive = ch_toupper(argv[argc -1][0]);
94 } else {
95 drive = get_default_drive();
Alistair Delvabeaee832021-02-24 11:27:23 -080096 }
97
Yi Kong39bbd962022-01-09 19:41:38 +080098 /* check out a drive whose letter and parameters match */
99 sprintf(errmsg, "Drive '%c:' not supported", drive);
Alistair Delvabeaee832021-02-24 11:27:23 -0800100 Stream = NULL;
101 for (dev=devices; dev->name; dev++) {
102 FREE(&Stream);
103 if (dev->drive != drive)
104 continue;
105 out_dev = *dev;
106 expand(dev->name,name);
107#ifdef USING_NEW_VOLD
108 strcpy(name, getVoldName(dev, name));
109#endif
110
Yi Kong39bbd962022-01-09 19:41:38 +0800111 Stream = OpenImage(&out_dev, dev, name, mode,
112 errmsg, ALWAYS_GET_GEOMETRY, mode, &maxSize,
113 NULL, NULL);
Alistair Delvabeaee832021-02-24 11:27:23 -0800114 if( !Stream)
115 continue;
116 break;
117 }
118
Yi Kong39bbd962022-01-09 19:41:38 +0800119 /* print error msg if needed */
120 if ( dev->drive == 0 )
121 goto exit_1;
Alistair Delvabeaee832021-02-24 11:27:23 -0800122
123 if (mode == O_WRONLY) {
Yi Kong39bbd962022-01-09 19:41:38 +0800124 size_t len;
125 mt_off_t size=0;
126 if(chs_to_totsectors(&out_dev, errmsg) < 0 ||
127 check_if_sectors_fit(out_dev.tot_sectors,
128 maxSize, 512, errmsg))
129 goto exit_1;
130 size = 512 * (mt_off_t) out_dev.tot_sectors;
Alistair Delvabeaee832021-02-24 11:27:23 -0800131 while ((len = fread(buf, 1,
132 bufLen(BUF_SIZE, size, address),
Yi Kong39bbd962022-01-09 19:41:38 +0800133 stdin)) > 0) {
134 ssize_t r = PWRITES(Stream, buf, address, len);
Alistair Delvabeaee832021-02-24 11:27:23 -0800135 fprintf(stderr, "Wrote to %d\n", (int) address);
136 if(r < 0)
137 break;
138 address += len;
139 }
140 } else {
Yi Kong39bbd962022-01-09 19:41:38 +0800141 ssize_t len;
142 while ((len = PREADS(Stream, buf, address, BUF_SIZE)) > 0) {
143 fwrite(buf, 1, (size_t) len, stdout);
144 address += (size_t) len;
Alistair Delvabeaee832021-02-24 11:27:23 -0800145 }
146 }
147
148 FREE(&Stream);
149 exit(0);
Yi Kong39bbd962022-01-09 19:41:38 +0800150exit_1:
151 FREE(&Stream);
152 fprintf(stderr,"%s\n",errmsg);
153 exit(1);
Alistair Delvabeaee832021-02-24 11:27:23 -0800154}