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