]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pread.c
Add xfs_io into xfsprogs, an xfs_db-alike program for the XFS IO path
[thirdparty/xfsprogs-dev.git] / io / pread.c
1 /*
2 * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include <ctype.h>
35 #include "command.h"
36 #include "input.h"
37 #include "init.h"
38
39 static cmdinfo_t pread_cmd;
40
41 static void
42 pread_help(void)
43 {
44 printf(_(
45 "\n"
46 " reads a range of bytes in a specified block size from the given offset\n"
47 "\n"
48 " Example:\n"
49 " 'read -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n"
50 "\n"
51 " Reads a segment of the currently open file, optionally dumping it to the\n"
52 " standard output stream (with -v option) for subsequent inspection.\n"
53 " The reads are performed in sequential blocks starting at offset, with the\n"
54 " blocksize tunable using the -b option (default blocksize is 4096 bytes).\n"
55 "\n"));
56 }
57
58 void *buffer;
59 ssize_t buffersize;
60
61 int
62 alloc_buffer(
63 ssize_t bsize,
64 unsigned int seed)
65 {
66 if (bsize > buffersize) {
67 buffer = realloc(buffer, buffersize = bsize);
68 if (!buffer) {
69 perror("realloc");
70 buffersize = 0;
71 return 0;
72 }
73 }
74 memset(buffer, seed, buffersize);
75 return 1;
76 }
77
78 static void
79 dump_buffer(
80 off64_t offset,
81 ssize_t len)
82 {
83 int i, j;
84 char *p;
85
86 for (i = 0, p = (char *)buffer; i < len; i += 16) {
87 char *s = p;
88
89 printf("%08llx: ", (off64_t)i + offset);
90 for (j = 0; j < 16 && i + j < len; j++, p++)
91 printf("%02x ", *p);
92 printf(" ");
93 for (j = 0; j < 16 && i + j < len; j++, s++) {
94 if (isalnum(*s))
95 printf("%c", *s);
96 else
97 printf(".");
98 }
99 printf("\n");
100 }
101 }
102
103 int
104 read_buffer(
105 int fd,
106 off64_t offset,
107 ssize_t count,
108 ssize_t *total,
109 int verbose,
110 int onlyone)
111 {
112 ssize_t bytes;
113
114 *total = 0;
115 while (count > 0) {
116 bytes = pread64(fd, buffer, min(count,buffersize), offset);
117 if (bytes == 0)
118 break;
119 if (bytes < 0) {
120 perror("pread64");
121 return 0;
122 }
123 if (verbose)
124 dump_buffer(offset, bytes);
125 *total += bytes;
126 if (onlyone || bytes < count)
127 break;
128 offset += bytes;
129 count -= bytes;
130 }
131 return 1;
132 }
133
134 static int
135 pread_f(
136 int argc,
137 char **argv)
138 {
139 off64_t offset;
140 ssize_t count, total;
141 unsigned int bsize = 4096;
142 char *sp;
143 int vflag = 0;
144 int c;
145
146 while ((c = getopt(argc, argv, "b:v")) != EOF) {
147 switch (c) {
148 case 'b':
149 bsize = strtoul(optarg, &sp, 0);
150 if (!sp || sp == optarg) {
151 printf(_("non-numeric bsize -- %s\n"), optarg);
152 return 0;
153 }
154 break;
155 case 'v':
156 vflag = 1;
157 break;
158 default:
159 printf("%s %s\n", pread_cmd.name, pread_cmd.oneline);
160 return 0;
161 }
162 }
163 if (optind != argc - 2) {
164 printf("%s %s\n", pread_cmd.name, pread_cmd.oneline);
165 return 0;
166 }
167 offset = strtoul(argv[optind], &sp, 0);
168 if (!sp || sp == argv[optind]) {
169 printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
170 return 0;
171 }
172 optind++;
173 count = strtoul(argv[optind], &sp, 0);
174 if (!sp || sp == argv[optind]) {
175 printf(_("non-numeric length argument -- %s\n"), argv[optind]);
176 return 0;
177 }
178
179 if (!alloc_buffer(bsize, 0xabababab))
180 return 0;
181
182 if (!read_buffer(fdesc, offset, count, &total, vflag, 0))
183 return 0;
184
185 printf(_("read %u/%u bytes at offset %llu\n"), total, count, offset);
186 return 0;
187 }
188
189 void
190 pread_init(void)
191 {
192 pread_cmd.name = _("pread");
193 pread_cmd.altname = _("r");
194 pread_cmd.cfunc = pread_f;
195 pread_cmd.argmin = 2;
196 pread_cmd.argmax = -1;
197 pread_cmd.args = _("[-b bs] [-v] off len");
198 pread_cmd.oneline = _("reads a number of bytes at a specified offset");
199 pread_cmd.help = pread_help;
200
201 add_command(&pread_cmd);
202 }