aboutsummaryrefslogtreecommitdiffstats
path: root/fs/seq_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/seq_file.c')
-rw-r--r--fs/seq_file.c95
1 files changed, 79 insertions, 16 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c
index cdfd996ca6ef..3f54dbd6c49b 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -350,28 +350,40 @@ int seq_printf(struct seq_file *m, const char *f, ...)
350} 350}
351EXPORT_SYMBOL(seq_printf); 351EXPORT_SYMBOL(seq_printf);
352 352
353static char *mangle_path(char *s, char *p, char *esc)
354{
355 while (s <= p) {
356 char c = *p++;
357 if (!c) {
358 return s;
359 } else if (!strchr(esc, c)) {
360 *s++ = c;
361 } else if (s + 4 > p) {
362 break;
363 } else {
364 *s++ = '\\';
365 *s++ = '0' + ((c & 0300) >> 6);
366 *s++ = '0' + ((c & 070) >> 3);
367 *s++ = '0' + (c & 07);
368 }
369 }
370 return NULL;
371}
372
373/*
374 * return the absolute path of 'dentry' residing in mount 'mnt'.
375 */
353int seq_path(struct seq_file *m, struct path *path, char *esc) 376int seq_path(struct seq_file *m, struct path *path, char *esc)
354{ 377{
355 if (m->count < m->size) { 378 if (m->count < m->size) {
356 char *s = m->buf + m->count; 379 char *s = m->buf + m->count;
357 char *p = d_path(path, s, m->size - m->count); 380 char *p = d_path(path, s, m->size - m->count);
358 if (!IS_ERR(p)) { 381 if (!IS_ERR(p)) {
359 while (s <= p) { 382 s = mangle_path(s, p, esc);
360 char c = *p++; 383 if (s) {
361 if (!c) { 384 p = m->buf + m->count;
362 p = m->buf + m->count; 385 m->count = s - m->buf;
363 m->count = s - m->buf; 386 return s - p;
364 return s - p;
365 } else if (!strchr(esc, c)) {
366 *s++ = c;
367 } else if (s + 4 > p) {
368 break;
369 } else {
370 *s++ = '\\';
371 *s++ = '0' + ((c & 0300) >> 6);
372 *s++ = '0' + ((c & 070) >> 3);
373 *s++ = '0' + (c & 07);
374 }
375 } 387 }
376 } 388 }
377 } 389 }
@@ -380,6 +392,57 @@ int seq_path(struct seq_file *m, struct path *path, char *esc)
380} 392}
381EXPORT_SYMBOL(seq_path); 393EXPORT_SYMBOL(seq_path);
382 394
395/*
396 * Same as seq_path, but relative to supplied root.
397 *
398 * root may be changed, see __d_path().
399 */
400int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
401 char *esc)
402{
403 int err = -ENAMETOOLONG;
404 if (m->count < m->size) {
405 char *s = m->buf + m->count;
406 char *p;
407
408 spin_lock(&dcache_lock);
409 p = __d_path(path, root, s, m->size - m->count);
410 spin_unlock(&dcache_lock);
411 err = PTR_ERR(p);
412 if (!IS_ERR(p)) {
413 s = mangle_path(s, p, esc);
414 if (s) {
415 p = m->buf + m->count;
416 m->count = s - m->buf;
417 return 0;
418 }
419 }
420 }
421 m->count = m->size;
422 return err;
423}
424
425/*
426 * returns the path of the 'dentry' from the root of its filesystem.
427 */
428int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
429{
430 if (m->count < m->size) {
431 char *s = m->buf + m->count;
432 char *p = dentry_path(dentry, s, m->size - m->count);
433 if (!IS_ERR(p)) {
434 s = mangle_path(s, p, esc);
435 if (s) {
436 p = m->buf + m->count;
437 m->count = s - m->buf;
438 return s - p;
439 }
440 }
441 }
442 m->count = m->size;
443 return -1;
444}
445
383static void *single_start(struct seq_file *p, loff_t *pos) 446static void *single_start(struct seq_file *p, loff_t *pos)
384{ 447{
385 return NULL + (*pos == 0); 448 return NULL + (*pos == 0);