diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2013-09-03 12:00:44 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-09-04 00:13:11 -0400 |
| commit | 4b6ccca701ef5977d0ffbc2c932430dea88b38b6 (patch) | |
| tree | f8daa1243e24168fba2595c29805765856708673 /lib | |
| parent | cffe78d92c217a57f57ec6743f71adfe39ea543e (diff) | |
add formats for dentry/file pathnames
New formats: %p[dD][234]?. The next pointer is interpreted as struct dentry *
or struct file * resp. ('d' => dentry, 'D' => file) and the last component(s)
of pathname are printed (%pd => just the last one, %pd2 => the last two, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vsprintf.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 739a36366b79..26559bdb4c49 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/math64.h> | 26 | #include <linux/math64.h> |
| 27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/dcache.h> | ||
| 29 | #include <net/addrconf.h> | 30 | #include <net/addrconf.h> |
| 30 | 31 | ||
| 31 | #include <asm/page.h> /* for PAGE_SIZE */ | 32 | #include <asm/page.h> /* for PAGE_SIZE */ |
| @@ -532,6 +533,81 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec) | |||
| 532 | return buf; | 533 | return buf; |
| 533 | } | 534 | } |
| 534 | 535 | ||
| 536 | static void widen(char *buf, char *end, unsigned len, unsigned spaces) | ||
| 537 | { | ||
| 538 | size_t size; | ||
| 539 | if (buf >= end) /* nowhere to put anything */ | ||
| 540 | return; | ||
| 541 | size = end - buf; | ||
| 542 | if (size <= spaces) { | ||
| 543 | memset(buf, ' ', size); | ||
| 544 | return; | ||
| 545 | } | ||
| 546 | if (len) { | ||
| 547 | if (len > size - spaces) | ||
| 548 | len = size - spaces; | ||
| 549 | memmove(buf + spaces, buf, len); | ||
| 550 | } | ||
| 551 | memset(buf, ' ', spaces); | ||
| 552 | } | ||
| 553 | |||
| 554 | static noinline_for_stack | ||
| 555 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, | ||
| 556 | const char *fmt) | ||
| 557 | { | ||
| 558 | const char *array[4], *s; | ||
| 559 | const struct dentry *p; | ||
| 560 | int depth; | ||
| 561 | int i, n; | ||
| 562 | |||
| 563 | switch (fmt[1]) { | ||
| 564 | case '2': case '3': case '4': | ||
| 565 | depth = fmt[1] - '0'; | ||
| 566 | break; | ||
| 567 | default: | ||
| 568 | depth = 1; | ||
| 569 | } | ||
| 570 | |||
| 571 | rcu_read_lock(); | ||
| 572 | for (i = 0; i < depth; i++, d = p) { | ||
| 573 | p = ACCESS_ONCE(d->d_parent); | ||
| 574 | array[i] = ACCESS_ONCE(d->d_name.name); | ||
| 575 | if (p == d) { | ||
| 576 | if (i) | ||
| 577 | array[i] = ""; | ||
| 578 | i++; | ||
| 579 | break; | ||
| 580 | } | ||
| 581 | } | ||
| 582 | s = array[--i]; | ||
| 583 | for (n = 0; n != spec.precision; n++, buf++) { | ||
| 584 | char c = *s++; | ||
| 585 | if (!c) { | ||
| 586 | if (!i) | ||
| 587 | break; | ||
| 588 | c = '/'; | ||
| 589 | s = array[--i]; | ||
| 590 | } | ||
| 591 | if (buf < end) | ||
| 592 | *buf = c; | ||
| 593 | } | ||
| 594 | rcu_read_unlock(); | ||
| 595 | if (n < spec.field_width) { | ||
| 596 | /* we want to pad the sucker */ | ||
| 597 | unsigned spaces = spec.field_width - n; | ||
| 598 | if (!(spec.flags & LEFT)) { | ||
| 599 | widen(buf - n, end, n, spaces); | ||
| 600 | return buf + spaces; | ||
| 601 | } | ||
| 602 | while (spaces--) { | ||
| 603 | if (buf < end) | ||
| 604 | *buf = ' '; | ||
| 605 | ++buf; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | return buf; | ||
| 609 | } | ||
| 610 | |||
| 535 | static noinline_for_stack | 611 | static noinline_for_stack |
| 536 | char *symbol_string(char *buf, char *end, void *ptr, | 612 | char *symbol_string(char *buf, char *end, void *ptr, |
| 537 | struct printf_spec spec, const char *fmt) | 613 | struct printf_spec spec, const char *fmt) |
| @@ -1253,6 +1329,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1253 | spec.base = 16; | 1329 | spec.base = 16; |
| 1254 | return number(buf, end, | 1330 | return number(buf, end, |
| 1255 | (unsigned long long) *((phys_addr_t *)ptr), spec); | 1331 | (unsigned long long) *((phys_addr_t *)ptr), spec); |
| 1332 | case 'd': | ||
| 1333 | return dentry_name(buf, end, ptr, spec, fmt); | ||
| 1334 | case 'D': | ||
| 1335 | return dentry_name(buf, end, | ||
| 1336 | ((const struct file *)ptr)->f_path.dentry, | ||
| 1337 | spec, fmt); | ||
| 1256 | } | 1338 | } |
| 1257 | spec.flags |= SMALL; | 1339 | spec.flags |= SMALL; |
| 1258 | if (spec.field_width == -1) { | 1340 | if (spec.field_width == -1) { |
