]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/crc.c
xfs: zero length symlinks are not valid
[thirdparty/xfsprogs-dev.git] / db / crc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2016 Red Hat, Inc.
4 * All Rights Reserved.
5 */
6
7 #include "libxfs.h"
8 #include "addr.h"
9 #include "command.h"
10 #include "type.h"
11 #include "faddr.h"
12 #include "fprint.h"
13 #include "field.h"
14 #include "flist.h"
15 #include "io.h"
16 #include "init.h"
17 #include "output.h"
18 #include "bit.h"
19 #include "print.h"
20 #include "crc.h"
21
22 static int crc_f(int argc, char **argv);
23 static void crc_help(void);
24
25 static const cmdinfo_t crc_cmd =
26 { "crc", NULL, crc_f, 0, 1, 0, "[-i|-r|-v]",
27 N_("manipulate crc values for V5 filesystem structures"), crc_help };
28
29 void
30 crc_init(void)
31 {
32 if (xfs_sb_version_hascrc(&mp->m_sb))
33 add_command(&crc_cmd);
34 }
35
36 static void
37 crc_help(void)
38 {
39 dbprintf(_(
40 "\n"
41 " 'crc' validates, invalidates, or recalculates the crc value for\n"
42 " the current on-disk metadata structures in Version 5 filesystems.\n"
43 "\n"
44 " Usage: \"crc [-i|-r|-v]\"\n"
45 "\n"
46 ));
47
48 }
49
50 static int
51 crc_f(
52 int argc,
53 char **argv)
54 {
55 const struct xfs_buf_ops *stashed_ops = NULL;
56 extern char *progname;
57 const field_t *fields;
58 const ftattr_t *fa;
59 flist_t *fl;
60 int invalidate = 0;
61 int recalculate = 0;
62 int validate = 0;
63 int c;
64
65 if (cur_typ == NULL) {
66 dbprintf(_("no current type\n"));
67 return 0;
68 }
69
70 if (cur_typ->fields == NULL) {
71 dbprintf(_("current type (%s) is not a structure\n"),
72 cur_typ->name);
73 return 0;
74 }
75
76 if (argc) while ((c = getopt(argc, argv, "irv")) != EOF) {
77 switch (c) {
78 case 'i':
79 invalidate = 1;
80 break;
81 case 'r':
82 recalculate = 1;
83 break;
84 case 'v':
85 validate = 1;
86 break;
87 default:
88 dbprintf(_("bad option for crc command\n"));
89 return 0;
90 }
91 } else
92 validate = 1;
93
94 if (invalidate + recalculate + validate > 1) {
95 dbprintf(_("crc command accepts only one option\n"));
96 return 0;
97 }
98
99 if ((invalidate || recalculate) &&
100 ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode)) {
101 dbprintf(_("%s not in expert mode, writing disabled\n"),
102 progname);
103 return 0;
104 }
105
106 fields = cur_typ->fields;
107
108 /* if we're a root field type, go down 1 layer to get field list */
109 if (fields->name[0] == '\0') {
110 fa = &ftattrtab[fields->ftyp];
111 ASSERT(fa->ftyp == fields->ftyp);
112 fields = fa->subfld;
113 }
114
115 /* Search for a CRC field */
116 fl = flist_find_ftyp(fields, FLDT_CRC);
117 if (!fl) {
118 dbprintf(_("No CRC field found for type %s\n"), cur_typ->name);
119 return 0;
120 }
121
122 /* run down the field list and set offsets into the data */
123 if (!flist_parse(fields, fl, iocur_top->data, 0)) {
124 flist_free(fl);
125 dbprintf(_("parsing error\n"));
126 return 0;
127 }
128
129 if (invalidate) {
130 struct xfs_buf_ops nowrite_ops;
131 flist_t *sfl;
132 int bit_length;
133 int parentoffset;
134 uint32_t crc;
135
136 sfl = fl;
137 parentoffset = 0;
138 while (sfl->child) {
139 parentoffset = sfl->offset;
140 sfl = sfl->child;
141 }
142 ASSERT(sfl->fld->ftyp == FLDT_CRC);
143
144 bit_length = fsize(sfl->fld, iocur_top->data, parentoffset, 0);
145 bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset);
146 crc = getbitval(iocur_top->data, sfl->offset, bit_length,
147 BVUNSIGNED);
148 /* Off by one, ignore endianness - we're just corrupting it. */
149 crc++;
150 setbitval(iocur_top->data, sfl->offset, bit_length, &crc);
151
152 /* Temporarily remove write verifier to write a bad CRC */
153 stashed_ops = iocur_top->bp->b_ops;
154 nowrite_ops.verify_read = stashed_ops->verify_read;
155 nowrite_ops.verify_write = xfs_dummy_verify;
156 iocur_top->bp->b_ops = &nowrite_ops;
157 }
158
159 if (invalidate || recalculate) {
160 if (invalidate)
161 dbprintf(_("Invalidating CRC:\n"));
162 else
163 dbprintf(_("Recalculating CRC:\n"));
164
165 write_cur();
166 if (stashed_ops)
167 iocur_top->bp->b_ops = stashed_ops;
168 /* re-verify to get proper b_error state */
169 iocur_top->bp->b_ops->verify_read(iocur_top->bp);
170 } else
171 dbprintf(_("Verifying CRC:\n"));
172
173 /* And show us what we've got! */
174 flist_print(fl);
175 print_flist(fl);
176 flist_free(fl);
177 return 0;
178 }