diff options
Diffstat (limited to 'lib/vsprintf.c')
| -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 @@  #include <linux/math64.h>  #include <linux/uaccess.h>  #include <linux/ioport.h> +#include <linux/dcache.h>  #include <net/addrconf.h>  #include <asm/page.h>		/* for PAGE_SIZE */ @@ -532,6 +533,81 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec)  	return buf;  } +static void widen(char *buf, char *end, unsigned len, unsigned spaces) +{ +	size_t size; +	if (buf >= end)	/* nowhere to put anything */ +		return; +	size = end - buf; +	if (size <= spaces) { +		memset(buf, ' ', size); +		return; +	} +	if (len) { +		if (len > size - spaces) +			len = size - spaces; +		memmove(buf + spaces, buf, len); +	} +	memset(buf, ' ', spaces); +} + +static noinline_for_stack +char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, +		  const char *fmt) +{ +	const char *array[4], *s; +	const struct dentry *p; +	int depth; +	int i, n; + +	switch (fmt[1]) { +		case '2': case '3': case '4': +			depth = fmt[1] - '0'; +			break; +		default: +			depth = 1; +	} + +	rcu_read_lock(); +	for (i = 0; i < depth; i++, d = p) { +		p = ACCESS_ONCE(d->d_parent); +		array[i] = ACCESS_ONCE(d->d_name.name); +		if (p == d) { +			if (i) +				array[i] = ""; +			i++; +			break; +		} +	} +	s = array[--i]; +	for (n = 0; n != spec.precision; n++, buf++) { +		char c = *s++; +		if (!c) { +			if (!i) +				break; +			c = '/'; +			s = array[--i]; +		} +		if (buf < end) +			*buf = c; +	} +	rcu_read_unlock(); +	if (n < spec.field_width) { +		/* we want to pad the sucker */ +		unsigned spaces = spec.field_width - n; +		if (!(spec.flags & LEFT)) { +			widen(buf - n, end, n, spaces); +			return buf + spaces; +		} +		while (spaces--) { +			if (buf < end) +				*buf = ' '; +			++buf; +		} +	} +	return buf; +} +  static noinline_for_stack  char *symbol_string(char *buf, char *end, void *ptr,  		    struct printf_spec spec, const char *fmt) @@ -1253,6 +1329,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,  		spec.base = 16;  		return number(buf, end,  			      (unsigned long long) *((phys_addr_t *)ptr), spec); +	case 'd': +		return dentry_name(buf, end, ptr, spec, fmt); +	case 'D': +		return dentry_name(buf, end, +				   ((const struct file *)ptr)->f_path.dentry, +				   spec, fmt);  	}  	spec.flags |= SMALL;  	if (spec.field_width == -1) { | 
