source: mainline/uspace/app/blkdump/blkdump.c@ 1d6dd2a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1d6dd2a was 1d6dd2a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Remove unnecessary includes from <stdio.h>.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
3 * Copyright (c) 2013 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file blockdump.c
36 * @brief Tool for dumping content of block devices
37 *
38 */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <stdint.h>
43#include <block.h>
44#include <mem.h>
45#include <loc.h>
46#include <byteorder.h>
47#include <scsi/mmc.h>
48#include <offset.h>
49#include <inttypes.h>
50#include <errno.h>
51#include <str.h>
52
53#define NAME "blkdump"
54
55static void syntax_print(void);
56static int print_blocks(aoff64_t block_offset, aoff64_t block_count, size_t block_size);
57static int print_toc(void);
58static void print_hex_row(uint8_t *data, size_t length, size_t bytes_per_row);
59
60static bool relative = false;
61static service_id_t service_id;
62
63int main(int argc, char **argv)
64{
65
66 errno_t rc;
67 char *dev_path;
68 size_t block_size;
69 char *endptr;
70 aoff64_t block_offset = 0;
71 aoff64_t block_count = 1;
72 aoff64_t dev_nblocks;
73 bool toc = false;
74
75 if (argc < 2) {
76 printf(NAME ": Error, argument missing.\n");
77 syntax_print();
78 return 1;
79 }
80
81 --argc; ++argv;
82
83 if (str_cmp(*argv, "--toc") == 0) {
84 --argc; ++argv;
85 toc = true;
86 goto devname;
87 }
88
89 if (str_cmp(*argv, "--relative") == 0) {
90 --argc; ++argv;
91 relative = true;
92 }
93
94 if (str_cmp(*argv, "--offset") == 0) {
95 --argc; ++argv;
96 if (*argv == NULL) {
97 printf(NAME ": Error, argument missing (offset).\n");
98 syntax_print();
99 return 1;
100 }
101
102 block_offset = strtol(*argv, &endptr, 10);
103 if (*endptr != '\0') {
104 printf(NAME ": Error, invalid argument (offset).\n");
105 syntax_print();
106 return 1;
107 }
108
109 --argc; ++argv;
110 }
111
112 if (str_cmp(*argv, "--count") == 0) {
113 --argc; ++argv;
114 if (*argv == NULL) {
115 printf(NAME ": Error, argument missing (count).\n");
116 syntax_print();
117 return 1;
118 }
119
120 block_count = strtol(*argv, &endptr, 10);
121 if (*endptr != '\0') {
122 printf(NAME ": Error, invalid argument (count).\n");
123 syntax_print();
124 return 1;
125 }
126
127 --argc; ++argv;
128 }
129
130devname:
131 if (argc != 1) {
132 printf(NAME ": Error, unexpected argument.\n");
133 syntax_print();
134 return 1;
135 }
136
137 dev_path = *argv;
138
139 rc = loc_service_get_id(dev_path, &service_id, 0);
140 if (rc != EOK) {
141 printf(NAME ": Error resolving device `%s'.\n", dev_path);
142 return 2;
143 }
144
145 rc = block_init(service_id, 2048);
146 if (rc != EOK) {
147 printf(NAME ": Error initializing libblock.\n");
148 return 2;
149 }
150
151 rc = block_get_bsize(service_id, &block_size);
152 if (rc != EOK) {
153 printf(NAME ": Error determining device block size.\n");
154 return 2;
155 }
156
157 rc = block_get_nblocks(service_id, &dev_nblocks);
158 if (rc != EOK) {
159 printf(NAME ": Warning, failed to obtain block device size.\n");
160 }
161
162 printf("Device %s has %" PRIuOFF64 " blocks, %" PRIuOFF64 " bytes each\n", dev_path, dev_nblocks, (aoff64_t) block_size);
163
164 int ret;
165 if (toc)
166 ret = print_toc();
167 else
168 ret = print_blocks(block_offset, block_count, block_size);
169
170 block_fini(service_id);
171
172 return ret;
173}
174
175static int print_blocks(aoff64_t block_offset, aoff64_t block_count, size_t block_size)
176{
177 uint8_t *data;
178 aoff64_t current;
179 aoff64_t limit;
180 size_t data_offset;
181 errno_t rc;
182
183 data = malloc(block_size);
184 if (data == NULL) {
185 printf(NAME ": Error allocating data buffer of %" PRIuOFF64 " bytes", (aoff64_t) block_size);
186 return 3;
187 }
188
189 limit = block_offset + block_count;
190 for (current = block_offset; current < limit; current++) {
191 rc = block_read_direct(service_id, current, 1, data);
192 if (rc != EOK) {
193 printf(NAME ": Error reading block at %" PRIuOFF64 " \n", current);
194 free(data);
195 return 3;
196 }
197
198 printf("---- Block %" PRIuOFF64 " (at %" PRIuOFF64 ") ----\n", current, current*block_size);
199
200 for (data_offset = 0; data_offset < block_size; data_offset += 16) {
201 if (relative) {
202 printf("%8" PRIxOFF64 ": ", (aoff64_t) data_offset);
203 }
204 else {
205 printf("%8" PRIxOFF64 ": ", current*block_size + data_offset);
206 }
207 print_hex_row(data+data_offset, block_size-data_offset, 16);
208 printf("\n");
209 }
210 printf("\n");
211 }
212
213 free(data);
214 return 0;
215}
216
217static int print_toc(void)
218{
219 scsi_toc_multisess_data_t toc;
220 errno_t rc;
221
222 rc = block_read_toc(service_id, 0, &toc, sizeof(toc));
223 if (rc != EOK)
224 return 1;
225
226 printf("Multisession Information:\n");
227 printf("\tFirst complete session: %" PRIu8 "\n", toc.first_sess);
228 printf("\tLast complete session: %" PRIu8 "\n", toc.last_sess);
229 printf("\tFirst track of last complete session:\n");
230 printf("\t\tADR / Control: 0x%" PRIx8 "\n", toc.ftrack_lsess.adr_control);
231 printf("\t\tTrack number: %" PRIu8 "\n", toc.ftrack_lsess.track_no);
232 printf("\t\tStart block address: %" PRIu32 "\n", toc.ftrack_lsess.start_addr);
233
234 return 0;
235}
236
237/**
238 * Print a row of 16 bytes as commonly seen in hexadecimal dumps
239 */
240static void print_hex_row(uint8_t *data, size_t length, size_t bytes_per_row) {
241 size_t pos;
242 uint8_t b;
243
244 if (length > bytes_per_row) {
245 length = bytes_per_row;
246 }
247
248 /* Print hexadecimal values */
249 for (pos = 0; pos < length; pos++) {
250 if (pos == length/2) {
251 printf(" ");
252 }
253 printf("%02hhX ", data[pos]);
254 }
255
256 /* Pad with spaces if we have less than 16 bytes */
257 for (pos = length; pos < bytes_per_row; pos++) {
258 if (pos == length/2) {
259 printf(" ");
260 }
261 printf(" ");
262 }
263
264 /* Print printable characters */
265 for (pos = 0; pos < length; pos++) {
266 if (pos == length/2) {
267 printf(" ");
268 }
269 b = data[pos];
270 if (b >= 32 && b < 128) {
271 putchar(b);
272 }
273 else {
274 putchar('.');
275 }
276 }
277}
278
279static void syntax_print(void)
280{
281 printf("syntax: blkdump [--toc] [--relative] [--offset <num_blocks>] "
282 "[--count <num_blocks>] <device_name>\n");
283}
284
285/**
286 * @}
287 */
Note: See TracBrowser for help on using the repository browser.