]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/crc.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / db / crc.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
b64af2c4
ES
2/*
3 * Copyright (c) 2016 Red Hat, Inc.
4 * All Rights Reserved.
b64af2c4
ES
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"
4a87b332 20#include "crc.h"
b64af2c4
ES
21
22static int crc_f(int argc, char **argv);
23static void crc_help(void);
24
25static 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
29void
30crc_init(void)
31{
2660e653 32 if (xfs_has_crc(mp))
b64af2c4
ES
33 add_command(&crc_cmd);
34}
35
36static void
37crc_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
50static int
51crc_f(
52 int argc,
53 char **argv)
54{
55 const struct xfs_buf_ops *stashed_ops = NULL;
a19679ec 56 struct xfs_buf_ops nowrite_ops;
b64af2c4
ES
57 extern char *progname;
58 const field_t *fields;
59 const ftattr_t *fa;
60 flist_t *fl;
61 int invalidate = 0;
62 int recalculate = 0;
63 int validate = 0;
64 int c;
65
66 if (cur_typ == NULL) {
67 dbprintf(_("no current type\n"));
68 return 0;
69 }
70
71 if (cur_typ->fields == NULL) {
72 dbprintf(_("current type (%s) is not a structure\n"),
73 cur_typ->name);
74 return 0;
75 }
76
77 if (argc) while ((c = getopt(argc, argv, "irv")) != EOF) {
78 switch (c) {
79 case 'i':
80 invalidate = 1;
81 break;
82 case 'r':
83 recalculate = 1;
84 break;
85 case 'v':
86 validate = 1;
87 break;
88 default:
89 dbprintf(_("bad option for crc command\n"));
90 return 0;
91 }
92 } else
93 validate = 1;
94
95 if (invalidate + recalculate + validate > 1) {
96 dbprintf(_("crc command accepts only one option\n"));
97 return 0;
98 }
99
100 if ((invalidate || recalculate) &&
23d88955 101 ((x.flags & LIBXFS_ISREADONLY) || !expert_mode)) {
b64af2c4
ES
102 dbprintf(_("%s not in expert mode, writing disabled\n"),
103 progname);
104 return 0;
105 }
106
107 fields = cur_typ->fields;
108
109 /* if we're a root field type, go down 1 layer to get field list */
110 if (fields->name[0] == '\0') {
111 fa = &ftattrtab[fields->ftyp];
112 ASSERT(fa->ftyp == fields->ftyp);
113 fields = fa->subfld;
114 }
115
116 /* Search for a CRC field */
a0d79cb3 117 fl = flist_find_ftyp(fields, FLDT_CRC, iocur_top->data, 0);
b64af2c4
ES
118 if (!fl) {
119 dbprintf(_("No CRC field found for type %s\n"), cur_typ->name);
120 return 0;
121 }
122
123 /* run down the field list and set offsets into the data */
124 if (!flist_parse(fields, fl, iocur_top->data, 0)) {
125 flist_free(fl);
126 dbprintf(_("parsing error\n"));
127 return 0;
128 }
129
130 if (invalidate) {
b64af2c4
ES
131 flist_t *sfl;
132 int bit_length;
133 int parentoffset;
8e1338fb 134 uint32_t crc;
b64af2c4
ES
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);
8e1338fb
ES
148 /* Off by one, ignore endianness - we're just corrupting it. */
149 crc++;
b64af2c4
ES
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}