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