]>
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; | |
3a2414fa | 65 | xfs_extnum_t nex; |
8c6cccd7 CH |
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) { | |
1665923a DW |
129 | xfs_daddr_t daddr = iocur_top->off >> BBSHIFT; |
130 | ||
131 | if (iocur_is_ddev(iocur_top)) | |
132 | dbprintf(_("datadev daddr is %lld\n"), daddr); | |
133 | else if (iocur_is_extlogdev(iocur_top)) | |
134 | dbprintf(_("logdev daddr is %lld\n"), daddr); | |
135 | else | |
136 | dbprintf(_("current daddr is %lld\n"), daddr); | |
137 | ||
2bd0ea18 NS |
138 | return 0; |
139 | } | |
14f8b681 | 140 | d = (int64_t)strtoull(argv[1], &p, 0); |
2bd0ea18 NS |
141 | if (*p != '\0' || |
142 | d >= mp->m_sb.sb_dblocks << (mp->m_sb.sb_blocklog - BBSHIFT)) { | |
9ee7055c | 143 | dbprintf(_("bad daddr %s\n"), argv[1]); |
2bd0ea18 NS |
144 | return 0; |
145 | } | |
146 | ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); | |
147 | set_cur(&typtab[TYP_DATA], d, 1, DB_RING_ADD, NULL); | |
148 | return 0; | |
149 | } | |
150 | ||
dfc130f3 | 151 | static void |
2bd0ea18 NS |
152 | dblock_help(void) |
153 | { | |
9ee7055c | 154 | dbprintf(_( |
2bd0ea18 NS |
155 | "\n Example:\n" |
156 | "\n" | |
157 | " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" | |
158 | " the inode's data fork. The filesystem block size is specified in the\n" | |
159 | " superblock.\n\n" | |
9ee7055c | 160 | )); |
2bd0ea18 NS |
161 | } |
162 | ||
163 | static int | |
164 | dblock_f( | |
165 | int argc, | |
166 | char **argv) | |
167 | { | |
168 | bbmap_t bbmap; | |
169 | bmap_ext_t *bmp; | |
5a35bf2c DC |
170 | xfs_fileoff_t bno; |
171 | xfs_fsblock_t dfsbno; | |
2bd0ea18 | 172 | int nb; |
3a2414fa | 173 | xfs_extnum_t nex; |
2bd0ea18 NS |
174 | char *p; |
175 | typnm_t type; | |
176 | ||
5a35bf2c | 177 | bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); |
2bd0ea18 | 178 | if (*p != '\0') { |
9ee7055c | 179 | dbprintf(_("bad block number %s\n"), argv[1]); |
2bd0ea18 NS |
180 | return 0; |
181 | } | |
182 | push_cur(); | |
183 | set_cur_inode(iocur_top->ino); | |
184 | type = inode_next_type(); | |
185 | pop_cur(); | |
186 | if (type == TYP_NONE) { | |
9ee7055c | 187 | dbprintf(_("no type for file data\n")); |
2bd0ea18 NS |
188 | return 0; |
189 | } | |
ff105f75 | 190 | nex = nb = type == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; |
2bd0ea18 NS |
191 | bmp = malloc(nb * sizeof(*bmp)); |
192 | bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); | |
193 | if (nex == 0) { | |
9ee7055c | 194 | dbprintf(_("file data block is unmapped\n")); |
2bd0ea18 NS |
195 | free(bmp); |
196 | return 0; | |
197 | } | |
198 | dfsbno = bmp->startblock + (bno - bmp->startoff); | |
199 | ASSERT(typtab[type].typnm == type); | |
200 | if (nex > 1) | |
201 | make_bbmap(&bbmap, nex, bmp); | |
14f8b681 | 202 | set_cur(&typtab[type], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), |
2bd0ea18 NS |
203 | nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); |
204 | free(bmp); | |
205 | return 0; | |
206 | } | |
207 | ||
dfc130f3 | 208 | static void |
2bd0ea18 NS |
209 | fsblock_help(void) |
210 | { | |
9ee7055c | 211 | dbprintf(_( |
2bd0ea18 NS |
212 | "\n Example:\n" |
213 | "\n" | |
214 | " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" | |
215 | " The filesystem block size is specified in the superblock and set during\n" | |
216 | " mkfs time. Offset is absolute (not AG relative).\n\n" | |
9ee7055c | 217 | )); |
2bd0ea18 NS |
218 | } |
219 | ||
220 | static int | |
221 | fsblock_f( | |
222 | int argc, | |
223 | char **argv) | |
224 | { | |
225 | xfs_agblock_t agbno; | |
226 | xfs_agnumber_t agno; | |
5a35bf2c | 227 | xfs_fsblock_t d; |
2bd0ea18 NS |
228 | char *p; |
229 | ||
230 | if (argc == 1) { | |
1665923a DW |
231 | if (!iocur_is_ddev(iocur_top)) { |
232 | dbprintf(_("cursor does not point to data device\n")); | |
233 | return 0; | |
234 | } | |
9ee7055c | 235 | dbprintf(_("current fsblock is %lld\n"), |
2bd0ea18 NS |
236 | XFS_DADDR_TO_FSB(mp, iocur_top->off >> BBSHIFT)); |
237 | return 0; | |
238 | } | |
239 | d = strtoull(argv[1], &p, 0); | |
240 | if (*p != '\0') { | |
9ee7055c | 241 | dbprintf(_("bad fsblock %s\n"), argv[1]); |
2bd0ea18 NS |
242 | return 0; |
243 | } | |
244 | agno = XFS_FSB_TO_AGNO(mp, d); | |
245 | agbno = XFS_FSB_TO_AGBNO(mp, d); | |
246 | if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks) { | |
9ee7055c | 247 | dbprintf(_("bad fsblock %s\n"), argv[1]); |
2bd0ea18 NS |
248 | return 0; |
249 | } | |
250 | ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); | |
251 | set_cur(&typtab[TYP_DATA], XFS_AGB_TO_DADDR(mp, agno, agbno), | |
252 | blkbb, DB_RING_ADD, NULL); | |
253 | return 0; | |
254 | } | |
255 | ||
256 | void | |
257 | print_block( | |
258 | const field_t *fields, | |
259 | int argc, | |
260 | char **argv) | |
261 | { | |
262 | print_rawdata(iocur_top->data, iocur_top->len); | |
263 | } | |
264 | ||
265 | static void | |
266 | print_rawdata( | |
267 | void *data, | |
268 | int len) | |
269 | { | |
270 | int i; | |
271 | int j; | |
272 | int lastaddr; | |
273 | int offchars; | |
274 | unsigned char *p; | |
275 | ||
276 | lastaddr = (len - 1) & ~(32 - 1); | |
277 | if (lastaddr < 0x10) | |
278 | offchars = 1; | |
279 | else if (lastaddr < 0x100) | |
280 | offchars = 2; | |
281 | else if (lastaddr < 0x1000) | |
282 | offchars = 3; | |
283 | else | |
284 | offchars = 4; | |
285 | for (i = 0, p = data; i < len; i += 32) { | |
286 | dbprintf("%-0*.*x:", offchars, offchars, i); | |
287 | for (j = 0; j < 32 && i + j < len; j++, p++) { | |
288 | if ((j & 3) == 0) | |
289 | dbprintf(" "); | |
290 | dbprintf("%02x", *p); | |
291 | } | |
292 | dbprintf("\n"); | |
293 | } | |
294 | } |