]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/convert.c
xfs_scrub_all: escape service names consistently
[thirdparty/xfsprogs-dev.git] / db / convert.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7 #include "libxfs.h"
8 #include "command.h"
9 #include "output.h"
10 #include "init.h"
11
12 #define M(A) (1 << CT_ ## A)
13 #define agblock_to_bytes(x) \
14 ((uint64_t)(x) << mp->m_sb.sb_blocklog)
15 #define agino_to_bytes(x) \
16 ((uint64_t)(x) << mp->m_sb.sb_inodelog)
17 #define agnumber_to_bytes(x) \
18 agblock_to_bytes((uint64_t)(x) * mp->m_sb.sb_agblocks)
19 #define daddr_to_bytes(x) \
20 ((uint64_t)(x) << BBSHIFT)
21 #define fsblock_to_bytes(x) \
22 (agnumber_to_bytes(XFS_FSB_TO_AGNO(mp, (x))) + \
23 agblock_to_bytes(XFS_FSB_TO_AGBNO(mp, (x))))
24 #define ino_to_bytes(x) \
25 (agnumber_to_bytes(XFS_INO_TO_AGNO(mp, (x))) + \
26 agino_to_bytes(XFS_INO_TO_AGINO(mp, (x))))
27 #define inoidx_to_bytes(x) \
28 ((uint64_t)(x) << mp->m_sb.sb_inodelog)
29
30 typedef enum {
31 CT_NONE = -1,
32 CT_AGBLOCK, /* xfs_agblock_t */
33 CT_AGINO, /* xfs_agino_t */
34 CT_AGNUMBER, /* xfs_agno_t */
35 CT_BBOFF, /* byte offset in daddr */
36 CT_BLKOFF, /* byte offset in fsb/agb */
37 CT_BYTE, /* byte in filesystem */
38 CT_DADDR, /* daddr_t */
39 CT_FSBLOCK, /* xfs_fsblock_t */
40 CT_INO, /* xfs_ino_t */
41 CT_INOIDX, /* index of inode in fsblock */
42 CT_INOOFF, /* byte offset in inode */
43 NCTS
44 } ctype_t;
45
46 typedef struct ctydesc {
47 ctype_t ctype;
48 int allowed;
49 const char **names;
50 } ctydesc_t;
51
52 typedef union {
53 xfs_agblock_t agblock;
54 xfs_agino_t agino;
55 xfs_agnumber_t agnumber;
56 int bboff;
57 int blkoff;
58 uint64_t byte;
59 xfs_daddr_t daddr;
60 xfs_fsblock_t fsblock;
61 xfs_ino_t ino;
62 int inoidx;
63 int inooff;
64 } cval_t;
65
66 static uint64_t bytevalue(ctype_t ctype, cval_t *val);
67 static int convert_f(int argc, char **argv);
68 static int getvalue(char *s, ctype_t ctype, cval_t *val);
69 static ctype_t lookupcty(char *ctyname);
70
71 static const char *agblock_names[] = { "agblock", "agbno", NULL };
72 static const char *agino_names[] = { "agino", "aginode", NULL };
73 static const char *agnumber_names[] = { "agnumber", "agno", NULL };
74 static const char *bboff_names[] = { "bboff", "daddroff", NULL };
75 static const char *blkoff_names[] = { "blkoff", "fsboff", "agboff",
76 NULL };
77 static const char *byte_names[] = { "byte", "fsbyte", NULL };
78 static const char *daddr_names[] = { "daddr", "bb", NULL };
79 static const char *fsblock_names[] = { "fsblock", "fsb", "fsbno", NULL };
80 static const char *ino_names[] = { "ino", "inode", NULL };
81 static const char *inoidx_names[] = { "inoidx", "offset", NULL };
82 static const char *inooff_names[] = { "inooff", "inodeoff", NULL };
83
84 static const ctydesc_t ctydescs[NCTS] = {
85 { CT_AGBLOCK, M(AGNUMBER)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
86 agblock_names },
87 { CT_AGINO, M(AGNUMBER)|M(INOOFF), agino_names },
88 { CT_AGNUMBER,
89 M(AGBLOCK)|M(AGINO)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
90 agnumber_names },
91 { CT_BBOFF, M(AGBLOCK)|M(AGNUMBER)|M(DADDR)|M(FSBLOCK), bboff_names },
92 { CT_BLKOFF, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK), blkoff_names },
93 { CT_BYTE, 0, byte_names },
94 { CT_DADDR, M(BBOFF), daddr_names },
95 { CT_FSBLOCK, M(BBOFF)|M(BLKOFF)|M(INOIDX), fsblock_names },
96 { CT_INO, M(INOOFF), ino_names },
97 { CT_INOIDX, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK)|M(INOOFF),
98 inoidx_names },
99 { CT_INOOFF,
100 M(AGBLOCK)|M(AGINO)|M(AGNUMBER)|M(FSBLOCK)|M(INO)|M(INOIDX),
101 inooff_names },
102 };
103
104 static const cmdinfo_t convert_cmd =
105 { "convert", NULL, convert_f, 3, 9, 0, "type num [type num]... type",
106 "convert from one address form to another", NULL };
107
108 static uint64_t
109 bytevalue(ctype_t ctype, cval_t *val)
110 {
111 switch (ctype) {
112 case CT_AGBLOCK:
113 return agblock_to_bytes(val->agblock);
114 case CT_AGINO:
115 return agino_to_bytes(val->agino);
116 case CT_AGNUMBER:
117 return agnumber_to_bytes(val->agnumber);
118 case CT_BBOFF:
119 return (uint64_t)val->bboff;
120 case CT_BLKOFF:
121 return (uint64_t)val->blkoff;
122 case CT_BYTE:
123 return val->byte;
124 case CT_DADDR:
125 return daddr_to_bytes(val->daddr);
126 case CT_FSBLOCK:
127 return fsblock_to_bytes(val->fsblock);
128 case CT_INO:
129 return ino_to_bytes(val->ino);
130 case CT_INOIDX:
131 return inoidx_to_bytes(val->inoidx);
132 case CT_INOOFF:
133 return (uint64_t)val->inooff;
134 case CT_NONE:
135 case NCTS:
136 break;
137 }
138 /* NOTREACHED */
139 return 0;
140 }
141
142 static int
143 convert_f(int argc, char **argv)
144 {
145 ctype_t c;
146 int conmask;
147 cval_t cvals[NCTS] = {};
148 int i;
149 int mask;
150 uint64_t v;
151 ctype_t wtype;
152
153 /* move past the "convert" command */
154 argc--;
155 argv++;
156
157 if ((argc % 2) != 1) {
158 dbprintf(_("bad argument count %d to convert, expected 3,5,7,9 "
159 "arguments\n"), argc);
160 return 0;
161 }
162 if ((wtype = lookupcty(argv[argc - 1])) == CT_NONE) {
163 dbprintf(_("unknown conversion type %s\n"), argv[argc - 1]);
164 return 0;
165 }
166
167 for (i = mask = conmask = 0; i < (argc - 1) / 2; i++) {
168 c = lookupcty(argv[i * 2]);
169 if (c == CT_NONE) {
170 dbprintf(_("unknown conversion type %s\n"), argv[i * 2]);
171 return 0;
172 }
173 if (c == wtype) {
174 dbprintf(_("result type same as argument\n"));
175 return 0;
176 }
177 if (conmask & (1 << c)) {
178 dbprintf(_("conflicting conversion type %s\n"),
179 argv[i * 2]);
180 return 0;
181 }
182 if (!getvalue(argv[i * 2 + 1], c, &cvals[c]))
183 return 0;
184 mask |= 1 << c;
185 conmask |= ~ctydescs[c].allowed;
186 }
187 if (cur_agno != NULLAGNUMBER && (conmask & M(AGNUMBER)) == 0) {
188 cvals[CT_AGNUMBER].agnumber = cur_agno;
189 mask |= M(AGNUMBER);
190 }
191 v = 0;
192 for (c = (ctype_t)0; c < NCTS; c++) {
193 if (!(mask & (1 << c)))
194 continue;
195 v += bytevalue(c, &cvals[c]);
196 }
197 switch (wtype) {
198 case CT_AGBLOCK:
199 v = xfs_daddr_to_agbno(mp, v >> BBSHIFT);
200 break;
201 case CT_AGINO:
202 v = (v >> mp->m_sb.sb_inodelog) %
203 XFS_AGB_TO_AGINO(mp, mp->m_sb.sb_agblocks);
204 break;
205 case CT_AGNUMBER:
206 v = xfs_daddr_to_agno(mp, v >> BBSHIFT);
207 break;
208 case CT_BBOFF:
209 v &= BBMASK;
210 break;
211 case CT_BLKOFF:
212 v &= mp->m_blockmask;
213 break;
214 case CT_BYTE:
215 break;
216 case CT_DADDR:
217 v >>= BBSHIFT;
218 break;
219 case CT_FSBLOCK:
220 v = XFS_DADDR_TO_FSB(mp, v >> BBSHIFT);
221 break;
222 case CT_INO:
223 v = XFS_AGINO_TO_INO(mp, xfs_daddr_to_agno(mp, v >> BBSHIFT),
224 (v >> mp->m_sb.sb_inodelog) %
225 XFS_AGB_TO_AGINO(mp, mp->m_sb.sb_agblocks));
226 break;
227 case CT_INOIDX:
228 v = (v >> mp->m_sb.sb_inodelog) & (mp->m_sb.sb_inopblock - 1);
229 break;
230 case CT_INOOFF:
231 v &= mp->m_sb.sb_inodesize - 1;
232 break;
233 case CT_NONE:
234 case NCTS:
235 /* NOTREACHED */
236 break;
237 }
238 dbprintf("0x%llx (%llu)\n", v, v);
239 return 0;
240 }
241
242 void
243 convert_init(void)
244 {
245 add_command(&convert_cmd);
246 }
247
248 static int
249 getvalue(char *s, ctype_t ctype, cval_t *val)
250 {
251 char *p;
252 uint64_t v;
253
254 v = strtoull(s, &p, 0);
255 if (*p != '\0') {
256 dbprintf(_("%s is not a number\n"), s);
257 return 0;
258 }
259 switch (ctype) {
260 case CT_AGBLOCK:
261 val->agblock = (xfs_agblock_t)v;
262 break;
263 case CT_AGINO:
264 val->agino = (xfs_agino_t)v;
265 break;
266 case CT_AGNUMBER:
267 val->agnumber = (xfs_agnumber_t)v;
268 break;
269 case CT_BBOFF:
270 val->bboff = (int)v;
271 break;
272 case CT_BLKOFF:
273 val->blkoff = (int)v;
274 break;
275 case CT_BYTE:
276 val->byte = (uint64_t)v;
277 break;
278 case CT_DADDR:
279 val->daddr = (xfs_daddr_t)v;
280 break;
281 case CT_FSBLOCK:
282 val->fsblock = (xfs_fsblock_t)v;
283 break;
284 case CT_INO:
285 val->ino = (xfs_ino_t)v;
286 break;
287 case CT_INOIDX:
288 val->inoidx = (int)v;
289 break;
290 case CT_INOOFF:
291 val->inooff = (int)v;
292 break;
293 case CT_NONE:
294 case NCTS:
295 /* NOTREACHED */
296 break;
297 }
298 return 1;
299 }
300
301 static ctype_t
302 lookupcty(char *ctyname)
303 {
304 ctype_t cty;
305 const char **name;
306
307 for (cty = (ctype_t)0; cty < NCTS; cty++) {
308 for (name = ctydescs[cty].names; *name; name++) {
309 if (strcmp(ctyname, *name) == 0)
310 return cty;
311 }
312 }
313 return CT_NONE;
314 }