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