source: trunk/src/lbatest/readsect.c@ 109

Last change on this file since 109 was 109, checked in by Markus Thielen, 14 years ago

added unaligned buffer option

File size: 8.3 KB
Line 
1/******************************************************************************
2
3 readsect.c - simple (dumb) HD sector read and test program
4
5 Author: Markus Thielen
6
7 Compilation (Watcom): wcl386 -bt=os2 readsect.c
8 wcl386 -bt=os2 -d3 readsect.c (for debug)
9
10 Copyright (c) 2010 by thi.guten Software development, www.thiguten.de
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26******************************************************************************/
27
28/*---- includes -------------------------------------------------------------*/
29
30#define INCL_DOS
31#define INCL_ERRORS
32#define INCL_DOSDEVICES
33#define INCL_DOSDEVIOCTL
34#include <os2.h>
35#include <stdio.h>
36#include <io.h>
37#include <stddef.h>
38#include <stdlib.h>
39#include <stdarg.h>
40#include <ctype.h>
41#include <string.h>
42#include <errno.h>
43
44#define SECTOR_SIZE 512
45#define SECTORS_PER_READ 4
46
47
48/*--- function prototypes ---------------------------------------------------*/
49
50void usage (void);
51
52int read_sectors (char *drv, unsigned long sectors_to_read,
53 unsigned long sectors_per_read, FILE *fpo);
54
55void log (char *fmt, ...);
56
57
58/*--- global data -----------------------------------------------------------*/
59
60char *log_fn = NULL;
61unsigned long buffer_offset = 0;
62
63
64/*--- start of code ---------------------------------------------------------*/
65
66/******************************************************************************
67 * main()
68 */
69int main(int argc, char **argv)
70{
71 char drv[50];
72 char *output;
73 FILE *fpo = NULL; /* output file */
74 int ret;
75 unsigned long sectors_to_read = 1024;
76 unsigned long i;
77 unsigned long sectors_per_read = SECTORS_PER_READ;
78 unsigned long loop_sectors_start = sectors_per_read;
79 int a;
80
81 if (argc < 4) {
82 usage();
83 return -1;
84 }
85
86 /* parse args */
87 for (a = 1; a < argc; a++) {
88
89 if (argv[a][0] != '-' && argv[a][0] != '/') {
90 fprintf(stderr, "unknown argument %s - aborting\n", argv[a]);
91 return (-1);
92 }
93
94 switch (tolower(argv[a][1])) {
95
96 case 'd':
97 /* drive spec */
98 if (isalpha(argv[++a][0])) {
99 sprintf(drv, "\\\\.\\%c", toupper(argv[a][0]));
100 } else if (isdigit(argv[a][0])) {
101 sprintf(drv, "\\\\.\\Physical_Disk%c", argv[a][0]);
102 } else {
103 usage();
104 return -1;
105 }
106 break;
107
108 case 's':
109 /* get sectors to read */
110 sectors_to_read = strtoul(argv[++a], NULL, 10);
111 break;
112
113 case 'o':
114 /* get output file */
115 output = argv[++a];
116 if (*output == '-' && output[1] == 0) {
117 /* use stdout */
118 fpo = stdout;
119 } else {
120 fpo = fopen(output, "wb");
121 if (!fpo) {
122 perror("Failed to open output file");
123 return(-1);
124 }
125 }
126 break;
127
128 case 'b':
129 /* optional buffer size */
130 if (*argv[++a] == '-') {
131 /* use a loop from 1 sectors to number specfied */
132 loop_sectors_start = 1;
133 sectors_per_read = (unsigned long) atoi(argv[a] + 1);
134 log("Looping sector count from 1 to %u; not using output file\n",
135 sectors_per_read);
136 if (fpo && fpo != stdin) {
137 fclose(fpo);
138 fpo = NULL;
139 }
140
141 } else {
142 /* just one run */
143 sectors_per_read = (unsigned long) atoi(argv[a]);
144 loop_sectors_start = sectors_per_read;
145 }
146 if (sectors_per_read == 0) {
147 sectors_per_read = SECTORS_PER_READ;
148 }
149 break;
150
151 case 'l':
152 /* optional log file name */
153 log_fn = argv[++a];
154 unlink(log_fn);
155 break;
156
157 case 'u':
158 /* use unaligned read buffer */
159 buffer_offset = 1;
160 break;
161 }
162 }
163
164 /* go */
165 for (i = loop_sectors_start; i <= sectors_per_read; i++) {
166 ret = read_sectors(drv, sectors_to_read, i, fpo);
167 }
168
169 if (fpo && fpo != stdout) {
170 fclose(fpo);
171 }
172
173 log("\nDone\n");
174 return ret;
175
176 }
177
178/******************************************************************************
179 * read_sectors() - read sectors and dump to output file
180 */
181int read_sectors(char *drv, unsigned long sectors_to_read,
182 unsigned long sectors_per_read, FILE *fpo)
183{
184 unsigned long ret;
185 HFILE hf_disk;
186 unsigned long action;
187 unsigned long cb_read;
188 char *buf;
189 int rc = 0;
190 unsigned long cb_take;
191 unsigned long sectors_take;
192 unsigned long sectors_read = 0;
193
194 buf = malloc(SECTOR_SIZE * sectors_per_read + buffer_offset);
195 log("\nusing %u sectors per read\n", sectors_per_read);
196 log("read buffer address: 0x%u %s\n", buf + buffer_offset,
197 buffer_offset ? "(unaligned)" : "");
198
199 /* open drive */
200 log("Getting handle for drive %s\n", drv);
201 ret = DosOpen(drv, &hf_disk, &action, 0, 0,
202 OPEN_ACTION_OPEN_IF_EXISTS,
203 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
204 NULL);
205 if (ret != NO_ERROR) {
206 fprintf(stderr, "Failed to open disk %s for reading: %d\n", drv, ret);
207 return -1;
208 }
209
210 /* go... */
211 while (sectors_read < sectors_to_read) {
212
213 sectors_take = min(sectors_to_read - sectors_read, sectors_per_read);
214 cb_take = SECTOR_SIZE * sectors_take;
215
216 log("\rReading %u sector(s) this run; (%u sectors read so far)...",
217 sectors_take, sectors_read);
218 ret = DosRead(hf_disk, buf + buffer_offset, cb_take, &cb_read);
219 if (ret != NO_ERROR) {
220 fprintf(stderr, "\nFailed to read from disk %s, code %d\n", drv, ret);
221 rc = -1;
222 break;
223 }
224
225 if (cb_read == 0) {
226 break;
227 }
228
229 if (cb_read != cb_take) {
230 log("\n\nRead only %u instead of %u bytes...\n\n", cb_read, cb_take);
231 break;
232 }
233
234 sectors_read += cb_read / SECTOR_SIZE;
235 if (fpo && fwrite(buf + buffer_offset, 1, cb_read, fpo) != cb_read) {
236 perror("Failed to write to output file");
237 rc = -1;
238 break;
239 }
240
241 }
242
243 log("\n%u sectors read.\n", sectors_read);
244
245 DosClose(hf_disk);
246 free(buf);
247
248 return rc;
249}
250
251/******************************************************************************
252 * usage() - print usage summary to STDOUT
253 */
254void usage(void)
255{
256 printf("readsect.exe - read HD sectors and store them to an output file.\n"
257 "Call with a drive letter (for logical drive) or 1-based disk number (for\n"
258 "physical drive)\n\n"
259 "Usage:\n\n"
260 "readsect <drive letter|number> <number of sectors> <outfile>\n"
261 " [<read buffer size>] [-lf <log file>] [-unaligned]\n"
262 "where:\n"
263 "-d drive letter drive letter of logical drive to read from\n"
264 " drive number 1-based physical disk number to read from\n"
265 "-s number of sectors number of sectors to read (e.g. 1024)\n"
266 "-o outfile path and filename of output file\n"
267 "-b read buffer size optional buffer size in number of sectors (512 byte)\n"
268 " (default is %d sectors)\n"
269 "-l log file optional log file name\n"
270 "-u use unaligned buffer\n",
271 SECTORS_PER_READ);
272}
273
274
275/*******************************************************************************
276 * log() - log a string to the log file (if any)
277 */
278void log(char *fmt, ...)
279{
280 va_list arglist;
281 FILE *fp;
282 char buf[500];
283
284 /* assemble arguments */
285 va_start(arglist, fmt);
286 vsprintf(buf, fmt, arglist);
287
288 if (log_fn && (fp = fopen(log_fn, "a")) != NULL) {
289 /* write string to log file */
290 fprintf(fp, buf);
291 fflush(fp);
292 fclose(fp);
293 }
294
295 /* write to stdout */
296 printf(buf);
297
298}
Note: See TracBrowser for help on using the repository browser.