aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-09-03 12:00:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-09-04 00:13:11 -0400
commit4b6ccca701ef5977d0ffbc2c932430dea88b38b6 (patch)
treef8daa1243e24168fba2595c29805765856708673 /lib/vsprintf.c
parentcffe78d92c217a57f57ec6743f71adfe39ea543e (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/vsprintf.c')
-rw-r--r--lib/vsprintf.c82
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
536static 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
554static noinline_for_stack
555char *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
535static noinline_for_stack 611static noinline_for_stack
536char *symbol_string(char *buf, char *end, void *ptr, 612char *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) {