dump/fsck: introduce print_xattr_entry

This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
and introduces print_xattr_entry which tries to parse an xattr entry
accroding to its xattr index.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
[Jaegeuk Kim: fix configure.ac]
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Sheng Yong 2017-11-03 12:25:12 +08:00 committed by Jaegeuk Kim
parent bbdbca4e22
commit ace53e2ff4
5 changed files with 191 additions and 15 deletions

View File

@ -93,7 +93,7 @@ AS_IF([test "x$have_blkid" = "xyes"],
# Checks for header files.
AC_CHECK_HEADERS([linux/fs.h linux/blkzoned.h fcntl.h mntent.h stdlib.h string.h \
sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h \
attr/xattr.h linux/xattr.h])
attr/xattr.h linux/xattr.h linux/posix_acl.h sys/acl.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE

View File

@ -492,17 +492,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
le32_to_cpu(node_blk->footer.nid) == ni.nid &&
ni.ino == ni.nid) {
print_node_info(node_blk, force);
print_node_info(sbi, node_blk, force);
dump_file(sbi, &ni, node_blk, force);
} else {
print_node_info(node_blk, force);
print_node_info(sbi, node_blk, force);
MSG(force, "Invalid (i)node block\n\n");
}
free(node_blk);
}
static void dump_node_from_blkaddr(u32 blk_addr)
static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
{
struct f2fs_node *node_blk;
int ret;
@ -514,9 +514,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
ASSERT(ret >= 0);
if (c.dbg_lv > 0)
print_node_info(node_blk, 0);
print_node_info(sbi, node_blk, 0);
else
print_inode_info(&node_blk->i, 1);
print_inode_info(sbi, node_blk, 1);
free(node_blk);
}
@ -640,7 +640,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
/* print inode */
if (c.dbg_lv > 0)
dump_node_from_blkaddr(ino_ni.blk_addr);
dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
@ -648,7 +648,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
nid, ni.blk_addr);
MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
ni.ino, ino_ni.blk_addr);
dump_node_from_blkaddr(ino_ni.blk_addr);
dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
dump_data_offset(ni.blk_addr,
le16_to_cpu(sum_entry.ofs_in_node));
} else {
@ -656,13 +656,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
if (ni.ino == ni.nid) {
MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
ni.ino, ino_ni.blk_addr);
dump_node_from_blkaddr(ino_ni.blk_addr);
dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
} else {
MSG(0, " - Node block : id = 0x%x from 0x%x\n",
nid, ni.blk_addr);
MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
ni.ino, ino_ni.blk_addr);
dump_node_from_blkaddr(ino_ni.blk_addr);
dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
dump_node_offset(ni.blk_addr);
}
}

View File

@ -147,8 +147,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);
extern void update_free_segments(struct f2fs_sb_info *);
void print_cp_state(u32);
extern void print_node_info(struct f2fs_node *, int);
extern void print_inode_info(struct f2fs_inode *, int);
extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
unsigned int, int *);

View File

@ -9,7 +9,14 @@
* published by the Free Software Foundation.
*/
#include "fsck.h"
#include "xattr.h"
#include <locale.h>
#ifdef HAVE_LINUX_POSIX_ACL_H
#include <linux/posix_acl.h>
#endif
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
u32 get_free_segments(struct f2fs_sb_info *sbi)
{
@ -35,8 +42,125 @@ void update_free_segments(struct f2fs_sb_info *sbi)
i++;
}
void print_inode_info(struct f2fs_inode *inode, int name)
#if defined(HAVE_LINUX_POSIX_ACL_H) || defined(HAVE_SYS_ACL_H)
void print_acl(char *value, int size)
{
struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
const char *end = value + size;
int i, count;
if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
return;
}
count = f2fs_acl_count(size);
if (count <= 0) {
MSG(0, "Invalid ACL value size %d\n", size);
return;
}
for (i = 0; i < count; i++) {
if ((char *)entry > end) {
MSG(0, "Invalid ACL entries count %d\n", count);
return;
}
switch (le16_to_cpu(entry->e_tag)) {
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
MSG(0, "tag:0x%x perm:0x%x\n",
le16_to_cpu(entry->e_tag),
le16_to_cpu(entry->e_perm));
entry = (struct f2fs_acl_entry *)((char *)entry +
sizeof(struct f2fs_acl_entry_short));
break;
case ACL_USER:
MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
le16_to_cpu(entry->e_tag),
le16_to_cpu(entry->e_perm),
le32_to_cpu(entry->e_id));
entry = (struct f2fs_acl_entry *)((char *)entry +
sizeof(struct f2fs_acl_entry));
break;
case ACL_GROUP:
MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
le16_to_cpu(entry->e_tag),
le16_to_cpu(entry->e_perm),
le32_to_cpu(entry->e_id));
entry = (struct f2fs_acl_entry *)((char *)entry +
sizeof(struct f2fs_acl_entry));
break;
default:
MSG(0, "Unknown ACL tag 0x%x\n",
le16_to_cpu(entry->e_tag));
return;
}
}
}
#else
#define print_acl(value, size) do { \
int i; \
for (i = 0; i < size; i++) \
MSG(0, "%02X", value[i]); \
MSG(0, "\n"); \
} while (0)
#endif
void print_xattr_entry(struct f2fs_xattr_entry *ent)
{
char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
struct fscrypt_context *ctx;
int i;
MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
MSG(0, "%c", ent->e_name[i]);
MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
ent->e_name_len, le16_to_cpu(ent->e_value_size));
switch (ent->e_name_index) {
case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
print_acl(value, le16_to_cpu(ent->e_value_size));
break;
case F2FS_XATTR_INDEX_USER:
case F2FS_XATTR_INDEX_SECURITY:
case F2FS_XATTR_INDEX_TRUSTED:
case F2FS_XATTR_INDEX_LUSTRE:
for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
MSG(0, "%02X", value[i]);
MSG(0, "\n");
break;
case F2FS_XATTR_INDEX_ENCRYPTION:
ctx = (struct fscrypt_context *)value;
MSG(0, "format: %d\n", ctx->format);
MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
MSG(0, "flags: 0x%x\n", ctx->flags);
MSG(0, "master_key_descriptor: ");
for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
MSG(0, "%02X", ctx->master_key_descriptor[i]);
MSG(0, "\nnonce: ");
for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
MSG(0, "%02X", ctx->nonce[i]);
MSG(0, "\n");
break;
default:
break;
}
}
void print_inode_info(struct f2fs_sb_info *sbi,
struct f2fs_node *node, int name)
{
struct f2fs_inode *inode = &node->i;
void *xattr_addr;
struct f2fs_xattr_entry *ent;
unsigned char en[F2FS_NAME_LEN + 1];
unsigned int i = 0;
int namelen = le32_to_cpu(inode->i_namelen);
@ -111,17 +235,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
DISP_u32(inode, i_nid[3]); /* indirect */
DISP_u32(inode, i_nid[4]); /* double indirect */
xattr_addr = read_all_xattrs(sbi, node);
list_for_each_xattr(ent, xattr_addr) {
print_xattr_entry(ent);
}
free(xattr_addr);
printf("\n");
}
void print_node_info(struct f2fs_node *node_block, int verbose)
void print_node_info(struct f2fs_sb_info *sbi,
struct f2fs_node *node_block, int verbose)
{
nid_t ino = le32_to_cpu(node_block->footer.ino);
nid_t nid = le32_to_cpu(node_block->footer.nid);
/* Is this inode? */
if (ino == nid) {
DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
print_inode_info(&node_block->i, verbose);
print_inode_info(sbi, node_block, verbose);
} else {
int i;
u32 *dump_blk = (u32 *)node_block;

View File

@ -31,6 +31,51 @@ struct f2fs_xattr_entry {
char e_name[0]; /* attribute name */
};
#define FS_KEY_DESCRIPTOR_SIZE 8
#define FS_KEY_DERIVATION_NONCE_SIZE 16
struct fscrypt_context {
u8 format;
u8 contents_encryption_mode;
u8 filenames_encryption_mode;
u8 flags;
u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
} __attribute__((packed));
#define F2FS_ACL_VERSION 0x0001
struct f2fs_acl_entry {
__le16 e_tag;
__le16 e_perm;
__le32 e_id;
};
struct f2fs_acl_entry_short {
__le16 e_tag;
__le16 e_perm;
};
struct f2fs_acl_header {
__le32 a_version;
};
static inline int f2fs_acl_count(int size)
{
ssize_t s;
size -= sizeof(struct f2fs_acl_header);
s = size - 4 * sizeof(struct f2fs_acl_entry_short);
if (s < 0) {
if (size % sizeof(struct f2fs_acl_entry_short))
return -1;
return size / sizeof(struct f2fs_acl_entry_short);
} else {
if (s % sizeof(struct f2fs_acl_entry))
return -1;
return s / sizeof(struct f2fs_acl_entry) + 4;
}
}
#define XATTR_ROUND (3)
#define XATTR_SELINUX_SUFFIX "selinux"