Whamcloud - gitweb
LU-16605 lfs: Add -n option to fid2path
[fs/lustre-release.git] / lustre / utils / ll_decode_linkea.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; if not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2016, DDN Storage Corporation.
24  */
25 /*
26  * lustre/utils/ll_decode_linkea.c
27  *
28  * Tool for printing the MDT link_ea structure on the objects
29  * in human readable form.
30  *
31  * Author: Li Xi <lixi@ddn.com>
32  */
33
34
35 #include <stdio.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 #include <sys/xattr.h>
42 #include <linux/lustre/lustre_fid.h>
43
44 #define BUFFER_SIZE 65536
45
46 static void print_name(const char *cp, int len)
47 {
48         unsigned char ch;
49
50         while (len--) {
51                 ch = *cp++;
52                 if (!isprint(ch) || ch == '\\')
53                         printf("\\x%02x", ch);
54                 else
55                         putchar(ch);
56         }
57 }
58
59 int decode_linkea(const char *fname)
60 {
61         char buf[BUFFER_SIZE];
62         struct link_ea_header *leh;
63         ssize_t size;
64         struct link_ea_entry *lee;
65         int i;
66         __u64 length;
67         int reclen;
68         struct lu_fid pfid;
69
70         size = getxattr(fname, "trusted.link", buf, BUFFER_SIZE);
71         if (size < 0) {
72                 if (errno == ERANGE) {
73                         fprintf(stderr, "%s: failed to read trusted.link "
74                                 "xattr, the buffer size %u might be too "
75                                 "small\n", fname, BUFFER_SIZE);
76                 } else {
77                         fprintf(stderr,
78                                 "%s: failed to read trusted.link xattr: %s\n",
79                                 fname, strerror(errno));
80                 }
81                 return -1;
82         }
83
84         leh = (struct link_ea_header *)buf;
85         if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
86                 leh->leh_magic = LINK_EA_MAGIC;
87                 leh->leh_reccount = __swab32(leh->leh_reccount);
88                 leh->leh_len = __swab64(leh->leh_len);
89         }
90         if (leh->leh_magic != LINK_EA_MAGIC) {
91                 fprintf(stderr,
92                         "%s: magic mismatch, expected 0x%lx, got 0x%x\n",
93                         fname, LINK_EA_MAGIC, leh->leh_magic);
94                 return -1;
95         }
96         if (leh->leh_reccount == 0) {
97                 fprintf(stderr, "%s: empty record count\n", fname);
98                 return -1;
99         }
100         if (leh->leh_len > size) {
101                 fprintf(stderr,
102                         "%s: invalid length %llu, should smaller than %zd\n",
103                         fname, (unsigned long long)leh->leh_len, size);
104                 return -1;
105         }
106
107         length = sizeof(struct link_ea_header);
108         lee = (struct link_ea_entry *)(leh + 1);
109         printf("%s: count %u\n", fname, leh->leh_reccount);
110         for (i = 0; i < leh->leh_reccount; i++) {
111                 reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
112                 length += reclen;
113                 if (length > leh->leh_len) {
114                         fprintf(stderr,
115                                 "%s: length exceeded, expected %llu, got %llu\n",
116                                 fname, (unsigned long long)leh->leh_len,
117                                 (unsigned long long)length);
118                         return -1;
119                 }
120                 memcpy(&pfid, &lee->lee_parent_fid, sizeof(pfid));
121                 fid_be_to_cpu(&pfid, &pfid);
122
123                 printf("    %d: pfid "DFID", name '", i, PFID(&pfid));
124                 print_name(lee->lee_name, reclen - (int)sizeof(*lee));
125                 printf("'\n");
126                 lee = (struct link_ea_entry *)((char *)lee + reclen);
127         }
128
129         if (length != leh->leh_len) {
130                 fprintf(stderr,
131                         "%s: length mismatch, expected %llu, got %llu\n",
132                         fname,
133                         (unsigned long long)leh->leh_len,
134                         (unsigned long long)length);
135                 return -1;
136         }
137
138         return 0;
139 }
140
141 int main(int argc, char *argv[])
142 {
143         int     rc = 0;
144         int     rc2;
145         int     i;
146
147         for (i = 1; i < argc; i++) {
148                 rc2 = decode_linkea(argv[i]);
149                 if (rc2 != 0)
150                         rc = rc2;
151         }
152
153         return rc;
154 }