| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "libxfs.h" |
| #include "block.h" |
| #include "bmap.h" |
| #include "command.h" |
| #include "type.h" |
| #include "faddr.h" |
| #include "fprint.h" |
| #include "field.h" |
| #include "inode.h" |
| #include "io.h" |
| #include "output.h" |
| #include "init.h" |
| |
| static int ablock_f(int argc, char **argv); |
| static void ablock_help(void); |
| static int daddr_f(int argc, char **argv); |
| static void daddr_help(void); |
| static int dblock_f(int argc, char **argv); |
| static void dblock_help(void); |
| static int fsblock_f(int argc, char **argv); |
| static void fsblock_help(void); |
| static void print_rawdata(void *data, int len); |
| |
| static const cmdinfo_t ablock_cmd = |
| { "ablock", NULL, ablock_f, 1, 1, 1, N_("filoff"), |
| N_("set address to file offset (attr fork)"), ablock_help }; |
| static const cmdinfo_t daddr_cmd = |
| { "daddr", NULL, daddr_f, 0, 1, 1, N_("[d]"), |
| N_("set address to daddr value"), daddr_help }; |
| static const cmdinfo_t dblock_cmd = |
| { "dblock", NULL, dblock_f, 1, 1, 1, N_("filoff"), |
| N_("set address to file offset (data fork)"), dblock_help }; |
| static const cmdinfo_t fsblock_cmd = |
| { "fsblock", "fsb", fsblock_f, 0, 1, 1, N_("[fsb]"), |
| N_("set address to fsblock value"), fsblock_help }; |
| |
| static void |
| ablock_help(void) |
| { |
| dbprintf(_( |
| "\n Example:\n" |
| "\n" |
| " 'ablock 23' - sets the file position to the 23rd filesystem block in\n" |
| " the inode's attribute fork. The filesystem block size is specified in\n" |
| " the superblock.\n\n" |
| )); |
| } |
| |
| /*ARGSUSED*/ |
| static int |
| ablock_f( |
| int argc, |
| char **argv) |
| { |
| bmap_ext_t bm; |
| xfs_fileoff_t bno; |
| xfs_fsblock_t dfsbno; |
| int haveattr; |
| int nex; |
| char *p; |
| |
| bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); |
| if (*p != '\0') { |
| dbprintf(_("bad block number %s\n"), argv[1]); |
| return 0; |
| } |
| push_cur(); |
| set_cur_inode(iocur_top->ino); |
| if (!iocur_top->data) { |
| pop_cur(); |
| dbprintf(_("no current inode\n")); |
| return 0; |
| } |
| haveattr = XFS_DFORK_Q((xfs_dinode_t *)iocur_top->data); |
| pop_cur(); |
| if (!haveattr) { |
| dbprintf(_("no attribute data for file\n")); |
| return 0; |
| } |
| nex = 1; |
| bmap(bno, 1, XFS_ATTR_FORK, &nex, &bm); |
| if (nex == 0) { |
| dbprintf(_("file attr block is unmapped\n")); |
| return 0; |
| } |
| dfsbno = bm.startblock + (bno - bm.startoff); |
| ASSERT(typtab[TYP_ATTR].typnm == TYP_ATTR); |
| set_cur(&typtab[TYP_ATTR], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), |
| blkbb, DB_RING_ADD, NULL); |
| return 0; |
| } |
| |
| void |
| block_init(void) |
| { |
| add_command(&ablock_cmd); |
| add_command(&daddr_cmd); |
| add_command(&dblock_cmd); |
| add_command(&fsblock_cmd); |
| } |
| |
| static void |
| daddr_help(void) |
| { |
| dbprintf(_( |
| "\n Example:\n" |
| "\n" |
| " 'daddr 102' - sets position to the 102nd absolute disk block\n" |
| " (512 byte block).\n" |
| )); |
| } |
| |
| static int |
| daddr_f( |
| int argc, |
| char **argv) |
| { |
| int64_t d; |
| char *p; |
| |
| if (argc == 1) { |
| dbprintf(_("current daddr is %lld\n"), iocur_top->off >> BBSHIFT); |
| return 0; |
| } |
| d = (int64_t)strtoull(argv[1], &p, 0); |
| if (*p != '\0' || |
| d >= mp->m_sb.sb_dblocks << (mp->m_sb.sb_blocklog - BBSHIFT)) { |
| dbprintf(_("bad daddr %s\n"), argv[1]); |
| return 0; |
| } |
| ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); |
| set_cur(&typtab[TYP_DATA], d, 1, DB_RING_ADD, NULL); |
| return 0; |
| } |
| |
| static void |
| dblock_help(void) |
| { |
| dbprintf(_( |
| "\n Example:\n" |
| "\n" |
| " 'dblock 23' - sets the file position to the 23rd filesystem block in\n" |
| " the inode's data fork. The filesystem block size is specified in the\n" |
| " superblock.\n\n" |
| )); |
| } |
| |
| static int |
| dblock_f( |
| int argc, |
| char **argv) |
| { |
| bbmap_t bbmap; |
| bmap_ext_t *bmp; |
| xfs_fileoff_t bno; |
| xfs_fsblock_t dfsbno; |
| int nb; |
| int nex; |
| char *p; |
| typnm_t type; |
| |
| bno = (xfs_fileoff_t)strtoull(argv[1], &p, 0); |
| if (*p != '\0') { |
| dbprintf(_("bad block number %s\n"), argv[1]); |
| return 0; |
| } |
| push_cur(); |
| set_cur_inode(iocur_top->ino); |
| type = inode_next_type(); |
| pop_cur(); |
| if (type == TYP_NONE) { |
| dbprintf(_("no type for file data\n")); |
| return 0; |
| } |
| nex = nb = type == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1; |
| bmp = malloc(nb * sizeof(*bmp)); |
| bmap(bno, nb, XFS_DATA_FORK, &nex, bmp); |
| if (nex == 0) { |
| dbprintf(_("file data block is unmapped\n")); |
| free(bmp); |
| return 0; |
| } |
| dfsbno = bmp->startblock + (bno - bmp->startoff); |
| ASSERT(typtab[type].typnm == type); |
| if (nex > 1) |
| make_bbmap(&bbmap, nex, bmp); |
| set_cur(&typtab[type], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), |
| nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); |
| free(bmp); |
| return 0; |
| } |
| |
| static void |
| fsblock_help(void) |
| { |
| dbprintf(_( |
| "\n Example:\n" |
| "\n" |
| " 'fsblock 1023' - sets the file position to the 1023rd filesystem block.\n" |
| " The filesystem block size is specified in the superblock and set during\n" |
| " mkfs time. Offset is absolute (not AG relative).\n\n" |
| )); |
| } |
| |
| static int |
| fsblock_f( |
| int argc, |
| char **argv) |
| { |
| xfs_agblock_t agbno; |
| xfs_agnumber_t agno; |
| xfs_fsblock_t d; |
| char *p; |
| |
| if (argc == 1) { |
| dbprintf(_("current fsblock is %lld\n"), |
| XFS_DADDR_TO_FSB(mp, iocur_top->off >> BBSHIFT)); |
| return 0; |
| } |
| d = strtoull(argv[1], &p, 0); |
| if (*p != '\0') { |
| dbprintf(_("bad fsblock %s\n"), argv[1]); |
| return 0; |
| } |
| agno = XFS_FSB_TO_AGNO(mp, d); |
| agbno = XFS_FSB_TO_AGBNO(mp, d); |
| if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks) { |
| dbprintf(_("bad fsblock %s\n"), argv[1]); |
| return 0; |
| } |
| ASSERT(typtab[TYP_DATA].typnm == TYP_DATA); |
| set_cur(&typtab[TYP_DATA], XFS_AGB_TO_DADDR(mp, agno, agbno), |
| blkbb, DB_RING_ADD, NULL); |
| return 0; |
| } |
| |
| void |
| print_block( |
| const field_t *fields, |
| int argc, |
| char **argv) |
| { |
| print_rawdata(iocur_top->data, iocur_top->len); |
| } |
| |
| static void |
| print_rawdata( |
| void *data, |
| int len) |
| { |
| int i; |
| int j; |
| int lastaddr; |
| int offchars; |
| unsigned char *p; |
| |
| lastaddr = (len - 1) & ~(32 - 1); |
| if (lastaddr < 0x10) |
| offchars = 1; |
| else if (lastaddr < 0x100) |
| offchars = 2; |
| else if (lastaddr < 0x1000) |
| offchars = 3; |
| else |
| offchars = 4; |
| for (i = 0, p = data; i < len; i += 32) { |
| dbprintf("%-0*.*x:", offchars, offchars, i); |
| for (j = 0; j < 32 && i + j < len; j++, p++) { |
| if ((j & 3) == 0) |
| dbprintf(" "); |
| dbprintf("%02x", *p); |
| } |
| dbprintf("\n"); |
| } |
| } |