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