| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "libxfs.h" |
| #include "command.h" |
| #include "type.h" |
| #include "faddr.h" |
| #include "fprint.h" |
| #include "field.h" |
| #include "io.h" |
| #include "print.h" |
| #include "bit.h" |
| #include "flist.h" |
| #include "strvec.h" |
| #include "output.h" |
| #include "sig.h" |
| #include "write.h" |
| |
| static void print_allfields(const struct field *fields); |
| static int print_f(int argc, char **argv); |
| static void print_flist_1(struct flist *flist, char **pfx, int parentoff); |
| static void print_somefields(const struct field *fields, int argc, |
| char **argv); |
| |
| static const cmdinfo_t print_cmd = |
| { "print", "p", print_f, 0, -1, 0, N_("[value]..."), |
| N_("print field values"), NULL }; |
| |
| static void |
| print_allfields( |
| const field_t *fields) |
| { |
| flist_t *flist; |
| #ifdef DEBUG |
| int i; |
| #endif |
| |
| flist = flist_make(""); |
| flist->fld = fields; |
| #ifndef DEBUG |
| (void)flist_parse(fields, flist, iocur_top->data, 0); |
| #else |
| i = flist_parse(fields, flist, iocur_top->data, 0); |
| ASSERT(i == 1); |
| #endif |
| flist_print(flist); |
| print_flist(flist); |
| flist_free(flist); |
| } |
| |
| static int |
| print_f( |
| int argc, |
| char **argv) |
| { |
| pfunc_t pf; |
| |
| if (cur_typ == NULL) { |
| dbprintf(_("no current type\n")); |
| return 0; |
| } |
| pf = cur_typ->pfunc; |
| if (pf == NULL) { |
| dbprintf(_("no print function for type %s\n"), cur_typ->name); |
| return 0; |
| } |
| argc--; |
| argv++; |
| (*pf)(DB_READ, cur_typ->fields, argc, argv); |
| return 0; |
| } |
| |
| void |
| print_flist( |
| flist_t *flist) |
| { |
| char **pfx; |
| |
| pfx = new_strvec(0); |
| print_flist_1(flist, pfx, 0); |
| free_strvec(pfx); |
| } |
| |
| static void |
| print_flist_1( |
| flist_t *flist, |
| char **ppfx, |
| int parentoff) |
| { |
| char buf[16]; |
| const field_t *f; |
| const ftattr_t *fa; |
| flist_t *fl; |
| int low; |
| int count; |
| int neednl; |
| char **pfx; |
| |
| for (fl = flist; fl && !seenint(); fl = fl->sibling) { |
| pfx = copy_strvec(ppfx); |
| if (fl->name[0]) |
| add_strvec(&pfx, fl->name); |
| if (fl->flags & FL_OKLOW) { |
| add_strvec(&pfx, "["); |
| snprintf(buf, sizeof(buf), "%d", fl->low); |
| add_strvec(&pfx, buf); |
| if (fl->low != fl->high) { |
| add_strvec(&pfx, "-"); |
| snprintf(buf, sizeof(buf), "%d", fl->high); |
| add_strvec(&pfx, buf); |
| } |
| add_strvec(&pfx, "]"); |
| } |
| if (fl->child) { |
| if (fl->name[0]) |
| add_strvec(&pfx, "."); |
| print_flist_1(fl->child, pfx, fl->offset); |
| } else { |
| f = fl->fld; |
| fa = &ftattrtab[f->ftyp]; |
| ASSERT(fa->ftyp == f->ftyp); |
| print_strvec(pfx); |
| dbprintf(" = "); |
| if (fl->flags & FL_OKLOW) |
| low = fl->low; |
| else |
| low = 0; |
| count = fcount(f, iocur_top->data, parentoff); |
| if (fl->flags & FL_OKHIGH) |
| count = min(count, fl->high - low + 1); |
| if (fa->prfunc) { |
| int fsz; |
| int bitlen; |
| |
| /* Don't read an array off the end of the buffer */ |
| fsz = fsize(f, iocur_top->data, parentoff, 0); |
| bitlen = iocur_top->len * NBBY; |
| if ((f->flags & FLD_ARRAY) && |
| fl->offset + (count * fsz) > bitlen) { |
| count = (bitlen - fl->offset) / fsz; |
| } |
| |
| neednl = fa->prfunc(iocur_top->data, fl->offset, |
| count, fa->fmtstr, fsz, fa->arg, low, |
| (f->flags & FLD_ARRAY) != 0); |
| if (neednl) |
| dbprintf("\n"); |
| } else if (fa->arg & FTARG_OKEMPTY) { |
| dbprintf(_("(empty)\n")); |
| } else { |
| dbprintf(_("Unrecognized metadata or type mismatch\n")); |
| } |
| } |
| free_strvec(pfx); |
| } |
| } |
| |
| void |
| print_init(void) |
| { |
| add_command(&print_cmd); |
| } |
| |
| void |
| print_sarray( |
| void *obj, |
| int bit, |
| int count, |
| int size, |
| int base, |
| int array, |
| const field_t *flds, |
| int skipnms) |
| { |
| int bitoff; |
| const field_t *f; |
| const ftattr_t *fa; |
| int first; |
| int i; |
| |
| ASSERT(bitoffs(bit) == 0); |
| if (skipnms == 0) { |
| for (f = flds, first = 1; f->name; f++) { |
| if (f->flags & FLD_SKIPALL) |
| continue; |
| dbprintf("%c%s", first ? '[' : ',', f->name); |
| first = 0; |
| } |
| dbprintf("] "); |
| } |
| for (i = 0, bitoff = bit; |
| i < count && !seenint(); |
| i++, bitoff += size) { |
| if (array) |
| dbprintf("\n%d:", i + base); |
| for (f = flds, first = 1; f->name; f++) { |
| if (f->flags & FLD_SKIPALL) |
| continue; |
| fa = &ftattrtab[f->ftyp]; |
| ASSERT(fa->ftyp == f->ftyp); |
| dbprintf("%c", first ? '[' : ','); |
| first = 0; |
| if (fa->prfunc) |
| fa->prfunc(obj, |
| bitoff + |
| bitoffset(f, obj, bitoff, i + base), |
| fcount(f, obj, bitoff), fa->fmtstr, |
| fsize(f, obj, bitoff, i + base), |
| fa->arg, (f->flags & FLD_ABASE1) != 0, |
| f->flags & FLD_ARRAY); |
| else { |
| ASSERT(fa->arg & FTARG_OKEMPTY); |
| dbprintf(_("(empty)")); |
| } |
| } |
| dbprintf("]"); |
| if (i < count - 1) |
| dbprintf(" "); |
| } |
| } |
| |
| static void |
| print_somefields( |
| const field_t *fields, |
| int argc, |
| char **argv) |
| { |
| const ftattr_t *fa; |
| flist_t *fl; |
| flist_t *lfl; |
| flist_t *nfl; |
| |
| fl = lfl = NULL; |
| while (argc > 0) { |
| nfl = flist_scan(*argv); |
| if (!nfl) { |
| if (fl) |
| flist_free(fl); |
| return; |
| } |
| if (lfl) |
| lfl->sibling = nfl; |
| else |
| fl = nfl; |
| lfl = nfl; |
| argc--; |
| argv++; |
| } |
| if (fields->name[0] == '\0') { |
| fa = &ftattrtab[fields->ftyp]; |
| ASSERT(fa->ftyp == fields->ftyp); |
| fields = fa->subfld; |
| } |
| if (!flist_parse(fields, fl, iocur_top->data, 0)) { |
| flist_free(fl); |
| return; |
| } |
| flist_print(fl); |
| print_flist(fl); |
| flist_free(fl); |
| } |
| |
| /*ARGSUSED*/ |
| void |
| print_string( |
| const field_t *fields, |
| int argc, |
| char **argv) |
| { |
| char *cp; |
| |
| if (argc != 0) |
| dbprintf(_("no arguments allowed\n")); |
| dbprintf("\""); |
| for (cp = iocur_top->data; |
| cp < (char *)iocur_top->data + iocur_top->len && *cp && |
| !seenint(); |
| cp++) |
| dbprintf("%c", *cp); |
| dbprintf("\"\n"); |
| } |
| |
| void |
| print_struct( |
| const field_t *fields, |
| int argc, |
| char **argv) |
| { |
| if (argc == 0) |
| print_allfields(fields); |
| else |
| print_somefields(fields, argc, argv); |
| } |