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

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

added incremental buffer size (loop) to readsect; added logging to readsect

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