|  | // 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); | 
|  | } |