1
0
Files
irix-657m-src/irix/cmd/xfs/db/convert.c
2022-09-29 17:59:04 +03:00

311 lines
7.4 KiB
C

#ident "$Revision: 1.8 $"
#include <sys/param.h>
#include <sys/uuid.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fs/xfs_types.h>
#include <sys/fs/xfs_inum.h>
#include <sys/fs/xfs_sb.h>
#include <sys/fs/xfs_ag.h>
#include <sys/fs/xfs_bit.h>
#include "sim.h"
#include "command.h"
#include "data.h"
#include "convert.h"
#include "output.h"
#include "mount.h"
#define M(A) (1 << CT_ ## A)
#define agblock_to_bytes(x) \
((__uint64_t)(x) << mp->m_sb.sb_blocklog)
#define agino_to_bytes(x) \
((__uint64_t)(x) << mp->m_sb.sb_inodelog)
#define agnumber_to_bytes(x) \
agblock_to_bytes((__uint64_t)(x) * mp->m_sb.sb_agblocks)
#define daddr_to_bytes(x) \
((__uint64_t)(x) << BBSHIFT)
#define fsblock_to_bytes(x) \
(agnumber_to_bytes(XFS_FSB_TO_AGNO(mp, (x))) + \
agblock_to_bytes(XFS_FSB_TO_AGBNO(mp, (x))))
#define ino_to_bytes(x) \
(agnumber_to_bytes(XFS_INO_TO_AGNO(mp, (x))) + \
agino_to_bytes(XFS_INO_TO_AGINO(mp, (x))))
#define inoidx_to_bytes(x) \
((__uint64_t)(x) << mp->m_sb.sb_inodelog)
typedef enum {
CT_NONE = -1,
CT_AGBLOCK, /* xfs_agblock_t */
CT_AGINO, /* xfs_agino_t */
CT_AGNUMBER, /* xfs_agno_t */
CT_BBOFF, /* byte offset in daddr */
CT_BLKOFF, /* byte offset in fsb/agb */
CT_BYTE, /* byte in filesystem */
CT_DADDR, /* daddr_t */
CT_FSBLOCK, /* xfs_fsblock_t */
CT_INO, /* xfs_ino_t */
CT_INOIDX, /* index of inode in fsblock */
CT_INOOFF, /* byte offset in inode */
NCTS
} ctype_t;
typedef struct ctydesc
{
ctype_t ctype;
int allowed;
const char **names;
} ctydesc_t;
typedef union
{
xfs_agblock_t agblock;
xfs_agino_t agino;
xfs_agnumber_t agnumber;
int bboff;
int blkoff;
__uint64_t byte;
daddr_t daddr;
xfs_fsblock_t fsblock;
xfs_ino_t ino;
int inoidx;
int inooff;
} cval_t;
static __uint64_t bytevalue(ctype_t ctype, cval_t *val);
static int convert_f(int argc, char **argv);
static int getvalue(char *s, ctype_t ctype, cval_t *val);
static ctype_t lookupcty(char *ctyname);
static const char *agblock_names[] = { "agblock", "agbno", NULL };
static const char *agino_names[] = { "agino", "aginode", NULL };
static const char *agnumber_names[] = { "agnumber", "agno", NULL };
static const char *bboff_names[] = { "bboff", "daddroff", NULL };
static const char *blkoff_names[] = { "blkoff", "fsboff", "agboff",
NULL };
static const char *byte_names[] = { "byte", "fsbyte", NULL };
static const char *daddr_names[] = { "daddr", "bb", NULL };
static const char *fsblock_names[] = { "fsblock", "fsb", "fsbno", NULL };
static const char *ino_names[] = { "ino", "inode", NULL };
static const char *inoidx_names[] = { "inoidx", "offset", NULL };
static const char *inooff_names[] = { "inooff", "inodeoff", NULL };
static const ctydesc_t ctydescs[NCTS] = {
{ CT_AGBLOCK, M(AGNUMBER)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
agblock_names },
{ CT_AGINO, M(AGNUMBER)|M(INOOFF), agino_names },
{ CT_AGNUMBER,
M(AGBLOCK)|M(AGINO)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
agnumber_names },
{ CT_BBOFF, M(AGBLOCK)|M(AGNUMBER)|M(DADDR)|M(FSBLOCK), bboff_names },
{ CT_BLKOFF, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK), blkoff_names },
{ CT_BYTE, 0, byte_names },
{ CT_DADDR, M(BBOFF), daddr_names },
{ CT_FSBLOCK, M(BBOFF)|M(BLKOFF)|M(INOIDX), fsblock_names },
{ CT_INO, M(INOOFF), ino_names },
{ CT_INOIDX, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK)|M(INOOFF),
inoidx_names },
{ CT_INOOFF,
M(AGBLOCK)|M(AGINO)|M(AGNUMBER)|M(FSBLOCK)|M(INO)|M(INOIDX),
inooff_names },
};
static const cmdinfo_t convert_cmd =
{ "convert", NULL, convert_f, 3, 9, 0, "type num [type num]... type",
"convert from one address form to another", NULL };
static __uint64_t
bytevalue(ctype_t ctype, cval_t *val)
{
switch (ctype) {
case CT_AGBLOCK:
return agblock_to_bytes(val->agblock);
case CT_AGINO:
return agino_to_bytes(val->agino);
case CT_AGNUMBER:
return agnumber_to_bytes(val->agnumber);
case CT_BBOFF:
return (__uint64_t)val->bboff;
case CT_BLKOFF:
return (__uint64_t)val->blkoff;
case CT_BYTE:
return val->byte;
case CT_DADDR:
return daddr_to_bytes(val->daddr);
case CT_FSBLOCK:
return fsblock_to_bytes(val->fsblock);
case CT_INO:
return ino_to_bytes(val->ino);
case CT_INOIDX:
return inoidx_to_bytes(val->inoidx);
case CT_INOOFF:
return (__uint64_t)val->inooff;
}
/*NOTREACHED*/
}
static int
convert_f(int argc, char **argv)
{
ctype_t c;
int conmask;
cval_t cvals[NCTS];
int i;
int mask;
__uint64_t v;
ctype_t wtype;
if ((argc % 2) != 1) {
dbprintf("bad argument count %d to convert, expected 3,5,7,9 "
"arguments\n",
argc);
return 0;
}
if ((wtype = lookupcty(argv[argc - 1])) == CT_NONE) {
dbprintf("unknown conversion type %s\n", argv[argc - 1]);
return 0;
}
for (i = mask = conmask = 0; i < (argc - 1) / 2; i++) {
c = lookupcty(argv[i * 2]);
if (c == CT_NONE) {
dbprintf("unknown conversion type %s\n", argv[i * 2]);
return 0;
}
if (c == wtype) {
dbprintf("result type same as argument\n");
return 0;
}
if (conmask & (1 << c)) {
dbprintf("conflicting conversion type %s\n",
argv[i * 2]);
return 0;
}
if (!getvalue(argv[i * 2 + 1], c, &cvals[c]))
return 0;
mask |= 1 << c;
conmask |= ~ctydescs[c].allowed;
}
if (cur_agno != NULLAGNUMBER && (conmask & M(AGNUMBER)) == 0) {
cvals[CT_AGNUMBER].agnumber = cur_agno;
mask |= M(AGNUMBER);
conmask |= ~ctydescs[CT_AGNUMBER].allowed;
}
v = 0;
for (c = (ctype_t)0; c < NCTS; c++) {
if (!(mask & (1 << c)))
continue;
v += bytevalue(c, &cvals[c]);
}
switch (wtype) {
case CT_AGBLOCK:
v = XFS_DADDR_TO_AGBNO(mp, v >> BBSHIFT);
break;
case CT_AGINO:
v = (v >> mp->m_sb.sb_inodelog) %
(mp->m_sb.sb_agblocks << mp->m_sb.sb_inopblog);
break;
case CT_AGNUMBER:
v = XFS_DADDR_TO_AGNO(mp, v >> BBSHIFT);
break;
case CT_BBOFF:
v &= BBMASK;
break;
case CT_BLKOFF:
v &= mp->m_blockmask;
break;
case CT_BYTE:
break;
case CT_DADDR:
v >>= BBSHIFT;
break;
case CT_FSBLOCK:
v = XFS_DADDR_TO_FSB(mp, v >> BBSHIFT);
break;
case CT_INO:
v = XFS_AGINO_TO_INO(mp, XFS_DADDR_TO_AGNO(mp, v >> BBSHIFT),
(v >> mp->m_sb.sb_inodelog) %
(mp->m_sb.sb_agblocks << mp->m_sb.sb_inopblog));
break;
case CT_INOIDX:
v = (v >> mp->m_sb.sb_inodelog) & (mp->m_sb.sb_inopblock - 1);
break;
case CT_INOOFF:
v &= mp->m_sb.sb_inodesize - 1;
break;
}
dbprintf("0x%llx (%llu)\n", v, v);
return 0;
}
void
convert_init(void)
{
add_command(&convert_cmd);
}
static int
getvalue(char *s, ctype_t ctype, cval_t *val)
{
char *p;
__uint64_t v;
v = strtoull(s, &p, 0);
if (*p != '\0') {
dbprintf("%s is not a number\n", s);
return 0;
}
switch (ctype) {
case CT_AGBLOCK:
val->agblock = (xfs_agblock_t)v;
break;
case CT_AGINO:
val->agino = (xfs_agino_t)v;
break;
case CT_AGNUMBER:
val->agnumber = (xfs_agnumber_t)v;
break;
case CT_BBOFF:
val->bboff = (int)v;
break;
case CT_BLKOFF:
val->blkoff = (int)v;
break;
case CT_BYTE:
val->byte = (__uint64_t)v;
break;
case CT_DADDR:
val->daddr = (daddr_t)v;
break;
case CT_FSBLOCK:
val->fsblock = (xfs_fsblock_t)v;
break;
case CT_INO:
val->ino = (xfs_ino_t)v;
break;
case CT_INOIDX:
val->inoidx = (int)v;
break;
case CT_INOOFF:
val->inooff = (int)v;
break;
}
return 1;
}
static ctype_t
lookupcty(char *ctyname)
{
ctype_t cty;
const char **name;
for (cty = (ctype_t)0; cty < NCTS; cty++) {
for (name = ctydescs[cty].names; *name; name++) {
if (strcmp(ctyname, *name) == 0)
return cty;
}
}
return CT_NONE;
}