Bump to 4.0.43
[platform/upstream/mtools.git] / mcat.c
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 "mtools.h"
24 #include "open_image.h"
25
26 static void usage(void) NORETURN;
27 static void usage(void)
28 {
29         fprintf(stderr, "Mtools version %s, dated %s\n",
30                 mversion, mdate);
31         fprintf(stderr, "Usage: mcat [-V] [-w] device\n");
32         fprintf(stderr, "       -w write on device else read\n");
33         exit(1);
34 }
35
36 #ifdef __CYGWIN__
37 #define BUF_SIZE 512u
38 #else
39 #define BUF_SIZE 16000u
40 #endif
41
42 static size_t bufLen(size_t blocksize, mt_off_t totalSize, mt_off_t address)
43 {
44         if(totalSize == 0)
45                 return blocksize;
46         if((mt_off_t) blocksize > totalSize - address)
47                 return (size_t) (totalSize - address);
48         return blocksize;
49 }
50
51 void mcat(int argc, char **argv, int type UNUSEDP) NORETURN;
52 void mcat(int argc, char **argv, int type UNUSEDP)
53 {
54         struct device *dev;
55         struct device out_dev;
56         char drive, name[EXPAND_BUF];
57         char errmsg[200];
58         Stream_t *Stream;
59         char buf[BUF_SIZE];
60
61         mt_off_t address = 0;
62         mt_off_t maxSize = 0;
63
64         char mode = O_RDONLY;
65         int c;
66
67         noPrivileges = 1;
68
69         if (argc < 2) {
70                 usage();
71         }
72
73         while ((c = getopt(argc,argv, "wi:"))!= EOF) {
74                 switch (c) {
75                 case 'w':
76                         mode = O_WRONLY;
77                         break;
78                 case 'i':
79                         set_cmd_line_image(optarg);
80                         break;
81                 default:
82                         usage();
83                 }
84         }
85
86         if (argc - optind > 1)
87                 usage();
88         if(argc - optind == 1) {
89                 if(!argv[optind][0] || argv[optind][1] != ':')
90                         usage();
91                 drive = ch_toupper(argv[argc -1][0]);
92         } else {
93                 drive = get_default_drive();
94         }
95
96         /* check out a drive whose letter and parameters match */
97         sprintf(errmsg, "Drive '%c:' not supported", drive);
98         Stream = NULL;
99         for (dev=devices; dev->name; dev++) {
100                 FREE(&Stream);
101                 if (dev->drive != drive)
102                         continue;
103                 out_dev = *dev;
104                 expand(dev->name,name);
105 #ifdef USING_NEW_VOLD
106                 strcpy(name, getVoldName(dev, name));
107 #endif
108
109                 Stream = OpenImage(&out_dev, dev, name, mode,
110                                    errmsg, ALWAYS_GET_GEOMETRY, mode, &maxSize,
111                                    NULL, NULL);
112                 if( !Stream)
113                         continue;
114                 break;
115         }
116
117         /* print error msg if needed */
118         if ( dev->drive == 0 )
119                 goto exit_1;
120
121         if (mode == O_WRONLY) {
122                 size_t len;
123                 mt_off_t size=0;
124                 if(chs_to_totsectors(&out_dev, errmsg) < 0 ||
125                    check_if_sectors_fit(out_dev.tot_sectors,
126                                         maxSize, 512, errmsg))
127                         goto exit_1;
128                 size = 512 * (mt_off_t) out_dev.tot_sectors;
129                 while ((len = fread(buf, 1,
130                                     bufLen(BUF_SIZE, size, address),
131                                     stdin)) > 0) {
132                         ssize_t r = PWRITES(Stream, buf, address, len);
133                         fprintf(stderr, "Wrote to %d\n", (int) address);
134                         if(r < 0)
135                                 break;
136                         address += len;
137                 }
138         } else {
139                 ssize_t len;
140                 while ((len = PREADS(Stream, buf, address, BUF_SIZE)) > 0) {
141                         fwrite(buf, 1, (size_t) len, stdout);
142                         address += (size_t) len;
143                 }
144         }
145
146         FREE(&Stream);
147         exit(0);
148 exit_1:
149         FREE(&Stream);
150         fprintf(stderr,"%s\n",errmsg);
151         exit(1);
152 }