]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2bd0ea18 | 2 | /* |
da23017d NS |
3 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
2bd0ea18 NS |
5 | */ |
6 | ||
6b803e5a | 7 | #include "libxfs.h" |
2bd0ea18 NS |
8 | #include "block.h" |
9 | #include "bmap.h" | |
10 | #include "command.h" | |
2bd0ea18 NS |
11 | #include "type.h" |
12 | #include "faddr.h" | |
13 | #include "fprint.h" | |
14 | #include "field.h" | |
15 | #include "inode.h" | |
16 | #include "io.h" | |
17 | #include "output.h" | |
4ca431fc | 18 | #include "init.h" |
2bd0ea18 NS |
19 | |
20 | static int ablock_f(int argc, char **argv); | |
21 | static void ablock_help(void); | |
22 | static int daddr_f(int argc, char **argv); | |
23 | static void daddr_help(void); | |
24 | static int dblock_f(int argc, char **argv); | |
25 | static void dblock_help(void); | |
26 | static int fsblock_f(int argc, char **argv); | |
27 | static void fsblock_help(void); | |
28 | static void print_rawdata(void *data, int len); | |
29 | ||
30 | static const cmdinfo_t ablock_cmd = | |
9ee7055c AM |
31 | { "ablock", NULL, ablock_f, 1, 1, 1, N_("filoff"), |
32 | N_("set address to file offset (attr fork)"), ablock_help }; | |
2bd0ea18 | 33 | static const cmdinfo_t daddr_cmd = |
9ee7055c AM |
34 | { "daddr", NULL, daddr_f, 0, 1, 1, N_("[d]"), |
35 | N_("set address to daddr value"), daddr_help }; | |
2bd0ea18 | 36 | static const cmdinfo_t dblock_cmd = |
9ee7055c AM |
37 | { "dblock", NULL, dblock_f, 1, 1, 1, N_("filoff"), |
38 | N_("set address to file offset (data fork)"), dblock_help }; | |
2bd0ea18 | 39 | static const cmdinfo_t fsblock_cmd = |
9ee7055c AM |
40 | { "fsblock", "fsb", fsblock_f, 0, 1, 1, N_("[fsb]"), |
41 | N_("set address to fsblock value"), fsblock_help }; | |
2bd0ea18 | 42 | |
dfc130f3 | 43 | static void |
2bd0ea18 NS |
44 | ablock_help(void) |
45 | { | |
9ee7055c | 46 | dbprintf(_( |
2bd0ea18 NS |
47 | "\n Example:\n" |
48 | "\n" | |
49 | " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" | |
50 | " the inode's attribute fork. The filesystem block size is specified in\n" | |
51 | " the superblock.\n\n" | |
9ee7055c | 52 | )); |
2bd0ea18 NS |
53 | } |
54 | ||
55 | /*ARGSUSED*/ | |
56 | static int | |
57 | ablock_f( | |
8c6cccd7 CH |
58 | int argc, |
59 | char **argv) | |
2bd0ea18 | 60 | { |
8c6cccd7 CH |
61 | bmap_ext_t bm; |
62 | xfs_fileoff_t bno; | |
63 | xfs_fsblock_t dfsbno; | |
64 | int haveattr; | |
65 | int nex; | |
66 | char *p; | |
67 | struct xfs_dinode *dip = iocur_top->data; | |
2bd0ea18 | 68 | |
5a35bf2c | 69 | bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); |
2bd0ea18 | 70 | if (*p != '\0') { |
9ee7055c | 71 | dbprintf(_("bad block number %s\n"), argv[1]); |
2bd0ea18 NS |
72 | return 0; |
73 | } | |
74 | push_cur(); | |
75 | set_cur_inode(iocur_top->ino); | |
8c6cccd7 | 76 | if (!dip) { |
de24d640 DW |
77 | pop_cur(); |
78 | dbprintf(_("no current inode\n")); | |
79 | return 0; | |
80 | } | |
8c6cccd7 | 81 | haveattr = dip->di_forkoff; |
2bd0ea18 NS |
82 | pop_cur(); |
83 | if (!haveattr) { | |
9ee7055c | 84 | dbprintf(_("no attribute data for file\n")); |
2bd0ea18 NS |
85 | return 0; |
86 | } | |
87 | nex = 1; | |
88 | bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); | |
89 | if (nex == 0) { | |
9ee7055c | 90 | dbprintf(_("file attr block is unmapped\n")); |
2bd0ea18 NS |
91 | return 0; |
92 | } | |
93 | dfsbno = bm.startblock + (bno - bm.startoff); | |
94 | ASSERT(typtab[TYP_ATTR].typnm == TYP_ATTR); | |
14f8b681 | 95 | set_cur(&typtab[TYP_ATTR], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), |
2bd0ea18 NS |
96 | blkbb, DB_RING_ADD, NULL); |
97 | return 0; | |
98 | } | |
99 | ||
100 | void | |
101 | block_init(void) | |
102 | { | |
103 | add_command(&ablock_cmd); | |
104 | add_command(&daddr_cmd); | |
105 | add_command(&dblock_cmd); | |
106 | add_command(&fsblock_cmd); | |
107 | } | |
108 | ||
dfc130f3 | 109 | static void |
2bd0ea18 NS |
110 | daddr_help(void) |
111 | { | |
9ee7055c | 112 | dbprintf(_( |
2bd0ea18 NS |
113 | "\n Example:\n" |
114 | "\n" | |
115 | " 'daddr 102' - sets position to the 102nd absolute disk block\n" | |
116 | " (512 byte block).\n" | |
9ee7055c | 117 | )); |
2bd0ea18 NS |
118 | } |
119 | ||
120 | static int | |
121 | daddr_f( | |
122 | int argc, | |
123 | char **argv) | |
124 | { | |
14f8b681 | 125 | int64_t d; |
2bd0ea18 NS |
126 | char *p; |
127 | ||
128 | if (argc == 1) { | |
9ee7055c | 129 | dbprintf(_("current daddr is %lld\n"), iocur_top->off >> BBSHIFT); |
2bd0ea18 NS |
130 | return 0; |
131 | } | |
14f8b681 | 132 | d = (int64_t)strtoull(argv[1], &p, 0); |
2bd0ea18 NS |
133 | if (*p != '\0' || |
134 | d >= mp->m_sb.sb_dblocks << (mp->m_sb.sb_blocklog - BBSHIFT)) { | |
9ee7055c | 135 | dbprintf(_("bad daddr %s\n"), argv[1]); |
2bd0ea18 NS |
136 | return 0; |
137 | } | |
138 | ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); | |
139 | set_cur(&typtab[TYP_DATA], d, 1, DB_RING_ADD, NULL); | |
140 | return 0; | |
141 | } | |
142 | ||
dfc130f3 | 143 | static void |
2bd0ea18 NS |
144 | dblock_help(void) |
145 | { | |
9ee7055c | 146 | dbprintf(_( |
2bd0ea18 NS |
147 | "\n Example:\n" |
148 | "\n" | |
149 | " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" | |
150 | " the inode's data fork. The filesystem block size is specified in the\n" | |
151 | " superblock.\n\n" | |
9ee7055c | 152 | )); |
2bd0ea18 NS |
153 | } |
154 | ||
155 | static int | |
156 | dblock_f( | |
157 | int argc, | |
158 | char **argv) | |
159 | { | |
160 | bbmap_t bbmap; | |
161 | bmap_ext_t *bmp; | |
5a35bf2c DC |
162 | xfs_fileoff_t bno; |
163 | xfs_fsblock_t dfsbno; | |
2bd0ea18 NS |
164 | int nb; |
165 | int nex; | |
166 | char *p; | |
167 | typnm_t type; | |
168 | ||
5a35bf2c | 169 | bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); |
2bd0ea18 | 170 | if (*p != '\0') { |
9ee7055c | 171 | dbprintf(_("bad block number %s\n"), argv[1]); |
2bd0ea18 NS |
172 | return 0; |
173 | } | |
174 | push_cur(); | |
175 | set_cur_inode(iocur_top->ino); | |
176 | type = inode_next_type(); | |
177 | pop_cur(); | |
178 | if (type == TYP_NONE) { | |
9ee7055c | 179 | dbprintf(_("no type for file data\n")); |
2bd0ea18 NS |
180 | return 0; |
181 | } | |
ff105f75 | 182 | nex = nb = type == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; |
2bd0ea18 NS |
183 | bmp = malloc(nb * sizeof(*bmp)); |
184 | bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); | |
185 | if (nex == 0) { | |
9ee7055c | 186 | dbprintf(_("file data block is unmapped\n")); |
2bd0ea18 NS |
187 | free(bmp); |
188 | return 0; | |
189 | } | |
190 | dfsbno = bmp->startblock + (bno - bmp->startoff); | |
191 | ASSERT(typtab[type].typnm == type); | |
192 | if (nex > 1) | |
193 | make_bbmap(&bbmap, nex, bmp); | |
14f8b681 | 194 | set_cur(&typtab[type], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), |
2bd0ea18 NS |
195 | nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); |
196 | free(bmp); | |
197 | return 0; | |
198 | } | |
199 | ||
dfc130f3 | 200 | static void |
2bd0ea18 NS |
201 | fsblock_help(void) |
202 | { | |
9ee7055c | 203 | dbprintf(_( |
2bd0ea18 NS |
204 | "\n Example:\n" |
205 | "\n" | |
206 | " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" | |
207 | " The filesystem block size is specified in the superblock and set during\n" | |
208 | " mkfs time. Offset is absolute (not AG relative).\n\n" | |
9ee7055c | 209 | )); |
2bd0ea18 NS |
210 | } |
211 | ||
212 | static int | |
213 | fsblock_f( | |
214 | int argc, | |
215 | char **argv) | |
216 | { | |
217 | xfs_agblock_t agbno; | |
218 | xfs_agnumber_t agno; | |
5a35bf2c | 219 | xfs_fsblock_t d; |
2bd0ea18 NS |
220 | char *p; |
221 | ||
222 | if (argc == 1) { | |
9ee7055c | 223 | dbprintf(_("current fsblock is %lld\n"), |
2bd0ea18 NS |
224 | XFS_DADDR_TO_FSB(mp, iocur_top->off >> BBSHIFT)); |
225 | return 0; | |
226 | } | |
227 | d = strtoull(argv[1], &p, 0); | |
228 | if (*p != '\0') { | |
9ee7055c | 229 | dbprintf(_("bad fsblock %s\n"), argv[1]); |
2bd0ea18 NS |
230 | return 0; |
231 | } | |
232 | agno = XFS_FSB_TO_AGNO(mp, d); | |
233 | agbno = XFS_FSB_TO_AGBNO(mp, d); | |
234 | if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks) { | |
9ee7055c | 235 | dbprintf(_("bad fsblock %s\n"), argv[1]); |
2bd0ea18 NS |
236 | return 0; |
237 | } | |
238 | ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); | |
239 | set_cur(&typtab[TYP_DATA], XFS_AGB_TO_DADDR(mp, agno, agbno), | |
240 | blkbb, DB_RING_ADD, NULL); | |
241 | return 0; | |
242 | } | |
243 | ||
244 | void | |
245 | print_block( | |
246 | const field_t *fields, | |
247 | int argc, | |
248 | char **argv) | |
249 | { | |
250 | print_rawdata(iocur_top->data, iocur_top->len); | |
251 | } | |
252 | ||
253 | static void | |
254 | print_rawdata( | |
255 | void *data, | |
256 | int len) | |
257 | { | |
258 | int i; | |
259 | int j; | |
260 | int lastaddr; | |
261 | int offchars; | |
262 | unsigned char *p; | |
263 | ||
264 | lastaddr = (len - 1) & ~(32 - 1); | |
265 | if (lastaddr < 0x10) | |
266 | offchars = 1; | |
267 | else if (lastaddr < 0x100) | |
268 | offchars = 2; | |
269 | else if (lastaddr < 0x1000) | |
270 | offchars = 3; | |
271 | else | |
272 | offchars = 4; | |
273 | for (i = 0, p = data; i < len; i += 32) { | |
274 | dbprintf("%-0*.*x:", offchars, offchars, i); | |
275 | for (j = 0; j < 32 && i + j < len; j++, p++) { | |
276 | if ((j & 3) == 0) | |
277 | dbprintf(" "); | |
278 | dbprintf("%02x", *p); | |
279 | } | |
280 | dbprintf("\n"); | |
281 | } | |
282 | } |