Commit d4dd167a authored by Miklos Szeredi's avatar Miklos Szeredi Committed by James Toy

Add two helpers that allow access to the seq_file's own buffer, but

hides the internal details of seq_files.

This allows easier implementation of special purpose filling
functions.  It also cleans up some existing functions which duplicated
the seq_file logic.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Andreas Gruenbacher <agruen@suse.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent cee0e35d
...@@ -418,6 +418,44 @@ char *mangle_path(char *s, char *p, char *esc) ...@@ -418,6 +418,44 @@ char *mangle_path(char *s, char *p, char *esc)
} }
EXPORT_SYMBOL(mangle_path); EXPORT_SYMBOL(mangle_path);
/**
* seq_get_buf - get buffer to write arbitrary data to
* @m: the seq_file handle
* @bufp: the beginning of the buffer is stored here
*
* Return the number of bytes available in the buffer, or zero if
* there's no space.
*/
size_t seq_get_buf(struct seq_file *m, char **bufp)
{
BUG_ON(m->count > m->size);
if (m->count < m->size)
*bufp = m->buf + m->count;
else
*bufp = NULL;
return m->size - m->count;
}
/**
* seq_commit - commit data to the buffer
* @m: the seq_file handle
* @num: the number of bytes to commit
*
* Commit @num bytes of data written to a buffer previously acquired
* by seq_buf_get. To signal an error condition, or that the data
* didn't fit in the available space, pass a negative @num value.
*/
void seq_commit(struct seq_file *m, int num)
{
if (num < 0) {
m->count = m->size;
} else {
BUG_ON(m->count + num > m->size);
m->count += num;
}
}
/** /**
* seq_path - seq_file interface to print a pathname * seq_path - seq_file interface to print a pathname
* @m: the seq_file handle * @m: the seq_file handle
...@@ -429,20 +467,21 @@ EXPORT_SYMBOL(mangle_path); ...@@ -429,20 +467,21 @@ EXPORT_SYMBOL(mangle_path);
*/ */
int seq_path(struct seq_file *m, struct path *path, char *esc) int seq_path(struct seq_file *m, struct path *path, char *esc)
{ {
if (m->count < m->size) { char *buf;
char *s = m->buf + m->count; size_t size = seq_get_buf(m, &buf);
char *p = d_path(path, s, m->size - m->count); int res = -1;
if (size) {
char *p = d_path(path, buf, size);
if (!IS_ERR(p)) { if (!IS_ERR(p)) {
s = mangle_path(s, p, esc); char *end = mangle_path(buf, p, esc);
if (s) { if (end)
p = m->buf + m->count; res = end - buf;
m->count = s - m->buf;
return s - p;
}
} }
} }
m->count = m->size; seq_commit(m, res);
return -1;
return res;
} }
EXPORT_SYMBOL(seq_path); EXPORT_SYMBOL(seq_path);
...@@ -454,27 +493,28 @@ EXPORT_SYMBOL(seq_path); ...@@ -454,27 +493,28 @@ EXPORT_SYMBOL(seq_path);
int seq_path_root(struct seq_file *m, struct path *path, struct path *root, int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
char *esc) char *esc)
{ {
int err = -ENAMETOOLONG; char *buf;
if (m->count < m->size) { size_t size = seq_get_buf(m, &buf);
char *s = m->buf + m->count; int res = -ENAMETOOLONG;
if (size) {
char *p; char *p;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
p = __d_path(path, root, s, m->size - m->count); p = __d_path(path, root, buf, size);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
err = PTR_ERR(p); res = PTR_ERR(p);
if (!IS_ERR(p)) { if (!IS_ERR(p)) {
s = mangle_path(s, p, esc); char *end = mangle_path(buf, p, esc);
if (s) { if (end)
p = m->buf + m->count; res = end - buf;
m->count = s - m->buf; else
return 0; res = -ENAMETOOLONG;
}
err = -ENAMETOOLONG;
} }
} }
m->count = m->size; seq_commit(m, res);
return err;
return res < 0 ? res : 0;
} }
/* /*
...@@ -482,20 +522,21 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, ...@@ -482,20 +522,21 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
*/ */
int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
{ {
if (m->count < m->size) { char *buf;
char *s = m->buf + m->count; size_t size = seq_get_buf(m, &buf);
char *p = dentry_path(dentry, s, m->size - m->count); int res = -1;
if (size) {
char *p = dentry_path(dentry, buf, size);
if (!IS_ERR(p)) { if (!IS_ERR(p)) {
s = mangle_path(s, p, esc); char *end = mangle_path(buf, p, esc);
if (s) { if (end)
p = m->buf + m->count; res = end - buf;
m->count = s - m->buf;
return s - p;
} }
} }
} seq_commit(m, res);
m->count = m->size;
return -1; return res;
} }
int seq_bitmap(struct seq_file *m, const unsigned long *bits, int seq_bitmap(struct seq_file *m, const unsigned long *bits,
......
...@@ -48,6 +48,9 @@ int seq_write(struct seq_file *seq, const void *data, size_t len); ...@@ -48,6 +48,9 @@ int seq_write(struct seq_file *seq, const void *data, size_t len);
int seq_printf(struct seq_file *, const char *, ...) int seq_printf(struct seq_file *, const char *, ...)
__attribute__ ((format (printf,2,3))); __attribute__ ((format (printf,2,3)));
size_t seq_get_buf(struct seq_file *m, char **bufp);
void seq_commit(struct seq_file *m, int num);
int seq_path(struct seq_file *, struct path *, char *); int seq_path(struct seq_file *, struct path *, char *);
int seq_dentry(struct seq_file *, struct dentry *, char *); int seq_dentry(struct seq_file *, struct dentry *, char *);
int seq_path_root(struct seq_file *m, struct path *path, struct path *root, int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment