seq_file: fix big-enough lseek() + read()
[linux-2.6.git] / fs / seq_file.c
1 /*
2  * linux/fs/seq_file.c
3  *
4  * helper functions for making synthetic files from sequences of records.
5  * initial implementation -- AV, Oct 2001.
6  */
7
8 #include <linux/fs.h>
9 #include <linux/module.h>
10 #include <linux/seq_file.h>
11 #include <linux/slab.h>
12
13 #include <asm/uaccess.h>
14 #include <asm/page.h>
15
16 /**
17  *      seq_open -      initialize sequential file
18  *      @file: file we initialize
19  *      @op: method table describing the sequence
20  *
21  *      seq_open() sets @file, associating it with a sequence described
22  *      by @op.  @op->start() sets the iterator up and returns the first
23  *      element of sequence. @op->stop() shuts it down.  @op->next()
24  *      returns the next element of sequence.  @op->show() prints element
25  *      into the buffer.  In case of error ->start() and ->next() return
26  *      ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
27  *      returns 0 in case of success and negative number in case of error.
28  *      Returning SEQ_SKIP means "discard this element and move on".
29  */
30 int seq_open(struct file *file, const struct seq_operations *op)
31 {
32         struct seq_file *p = file->private_data;
33
34         if (!p) {
35                 p = kmalloc(sizeof(*p), GFP_KERNEL);
36                 if (!p)
37                         return -ENOMEM;
38                 file->private_data = p;
39         }
40         memset(p, 0, sizeof(*p));
41         mutex_init(&p->lock);
42         p->op = op;
43
44         /*
45          * Wrappers around seq_open(e.g. swaps_open) need to be
46          * aware of this. If they set f_version themselves, they
47          * should call seq_open first and then set f_version.
48          */
49         file->f_version = 0;
50
51         /* SEQ files support lseek, but not pread/pwrite */
52         file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
53         return 0;
54 }
55 EXPORT_SYMBOL(seq_open);
56
57 static int traverse(struct seq_file *m, loff_t offset)
58 {
59         loff_t pos = 0, index;
60         int error = 0;
61         void *p;
62
63         m->version = 0;
64         index = 0;
65         m->count = m->from = 0;
66         if (!offset) {
67                 m->index = index;
68                 return 0;
69         }
70         if (!m->buf) {
71                 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
72                 if (!m->buf)
73                         return -ENOMEM;
74         }
75         p = m->op->start(m, &index);
76         while (p) {
77                 error = PTR_ERR(p);
78                 if (IS_ERR(p))
79                         break;
80                 error = m->op->show(m, p);
81                 if (error < 0)
82                         break;
83                 if (unlikely(error)) {
84                         error = 0;
85                         m->count = 0;
86                 }
87                 if (m->count == m->size)
88                         goto Eoverflow;
89                 if (pos + m->count > offset) {
90                         m->from = offset - pos;
91                         m->count -= m->from;
92                         m->index = index;
93                         break;
94                 }
95                 pos += m->count;
96                 m->count = 0;
97                 if (pos == offset) {
98                         index++;
99                         m->index = index;
100                         break;
101                 }
102                 p = m->op->next(m, p, &index);
103         }
104         m->op->stop(m, p);
105         m->index = index;
106         return error;
107
108 Eoverflow:
109         m->op->stop(m, p);
110         kfree(m->buf);
111         m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
112         return !m->buf ? -ENOMEM : -EAGAIN;
113 }
114
115 /**
116  *      seq_read -      ->read() method for sequential files.
117  *      @file: the file to read from
118  *      @buf: the buffer to read to
119  *      @size: the maximum number of bytes to read
120  *      @ppos: the current position in the file
121  *
122  *      Ready-made ->f_op->read()
123  */
124 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
125 {
126         struct seq_file *m = (struct seq_file *)file->private_data;
127         size_t copied = 0;
128         loff_t pos;
129         size_t n;
130         void *p;
131         int err = 0;
132
133         mutex_lock(&m->lock);
134         /*
135          * seq_file->op->..m_start/m_stop/m_next may do special actions
136          * or optimisations based on the file->f_version, so we want to
137          * pass the file->f_version to those methods.
138          *
139          * seq_file->version is just copy of f_version, and seq_file
140          * methods can treat it simply as file version.
141          * It is copied in first and copied out after all operations.
142          * It is convenient to have it as  part of structure to avoid the
143          * need of passing another argument to all the seq_file methods.
144          */
145         m->version = file->f_version;
146         /* grab buffer if we didn't have one */
147         if (!m->buf) {
148                 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
149                 if (!m->buf)
150                         goto Enomem;
151         }
152         /* if not empty - flush it first */
153         if (m->count) {
154                 n = min(m->count, size);
155                 err = copy_to_user(buf, m->buf + m->from, n);
156                 if (err)
157                         goto Efault;
158                 m->count -= n;
159                 m->from += n;
160                 size -= n;
161                 buf += n;
162                 copied += n;
163                 if (!m->count)
164                         m->index++;
165                 if (!size)
166                         goto Done;
167         }
168         /* we need at least one record in buffer */
169         pos = m->index;
170         p = m->op->start(m, &pos);
171         while (1) {
172                 err = PTR_ERR(p);
173                 if (!p || IS_ERR(p))
174                         break;
175                 err = m->op->show(m, p);
176                 if (err < 0)
177                         break;
178                 if (unlikely(err))
179                         m->count = 0;
180                 if (unlikely(!m->count)) {
181                         p = m->op->next(m, p, &pos);
182                         m->index = pos;
183                         continue;
184                 }
185                 if (m->count < m->size)
186                         goto Fill;
187                 m->op->stop(m, p);
188                 kfree(m->buf);
189                 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
190                 if (!m->buf)
191                         goto Enomem;
192                 m->count = 0;
193                 m->version = 0;
194                 pos = m->index;
195                 p = m->op->start(m, &pos);
196         }
197         m->op->stop(m, p);
198         m->count = 0;
199         goto Done;
200 Fill:
201         /* they want more? let's try to get some more */
202         while (m->count < size) {
203                 size_t offs = m->count;
204                 loff_t next = pos;
205                 p = m->op->next(m, p, &next);
206                 if (!p || IS_ERR(p)) {
207                         err = PTR_ERR(p);
208                         break;
209                 }
210                 err = m->op->show(m, p);
211                 if (m->count == m->size || err) {
212                         m->count = offs;
213                         if (likely(err <= 0))
214                                 break;
215                 }
216                 pos = next;
217         }
218         m->op->stop(m, p);
219         n = min(m->count, size);
220         err = copy_to_user(buf, m->buf, n);
221         if (err)
222                 goto Efault;
223         copied += n;
224         m->count -= n;
225         if (m->count)
226                 m->from = n;
227         else
228                 pos++;
229         m->index = pos;
230 Done:
231         if (!copied)
232                 copied = err;
233         else
234                 *ppos += copied;
235         file->f_version = m->version;
236         mutex_unlock(&m->lock);
237         return copied;
238 Enomem:
239         err = -ENOMEM;
240         goto Done;
241 Efault:
242         err = -EFAULT;
243         goto Done;
244 }
245 EXPORT_SYMBOL(seq_read);
246
247 /**
248  *      seq_lseek -     ->llseek() method for sequential files.
249  *      @file: the file in question
250  *      @offset: new position
251  *      @origin: 0 for absolute, 1 for relative position
252  *
253  *      Ready-made ->f_op->llseek()
254  */
255 loff_t seq_lseek(struct file *file, loff_t offset, int origin)
256 {
257         struct seq_file *m = (struct seq_file *)file->private_data;
258         loff_t retval = -EINVAL;
259
260         mutex_lock(&m->lock);
261         m->version = file->f_version;
262         switch (origin) {
263                 case 1:
264                         offset += file->f_pos;
265                 case 0:
266                         if (offset < 0)
267                                 break;
268                         retval = offset;
269                         if (offset != file->f_pos) {
270                                 while ((retval=traverse(m, offset)) == -EAGAIN)
271                                         ;
272                                 if (retval) {
273                                         /* with extreme prejudice... */
274                                         file->f_pos = 0;
275                                         m->version = 0;
276                                         m->index = 0;
277                                         m->count = 0;
278                                 } else {
279                                         retval = file->f_pos = offset;
280                                 }
281                         }
282         }
283         file->f_version = m->version;
284         mutex_unlock(&m->lock);
285         return retval;
286 }
287 EXPORT_SYMBOL(seq_lseek);
288
289 /**
290  *      seq_release -   free the structures associated with sequential file.
291  *      @file: file in question
292  *      @inode: file->f_path.dentry->d_inode
293  *
294  *      Frees the structures associated with sequential file; can be used
295  *      as ->f_op->release() if you don't have private data to destroy.
296  */
297 int seq_release(struct inode *inode, struct file *file)
298 {
299         struct seq_file *m = (struct seq_file *)file->private_data;
300         kfree(m->buf);
301         kfree(m);
302         return 0;
303 }
304 EXPORT_SYMBOL(seq_release);
305
306 /**
307  *      seq_escape -    print string into buffer, escaping some characters
308  *      @m:     target buffer
309  *      @s:     string
310  *      @esc:   set of characters that need escaping
311  *
312  *      Puts string into buffer, replacing each occurrence of character from
313  *      @esc with usual octal escape.  Returns 0 in case of success, -1 - in
314  *      case of overflow.
315  */
316 int seq_escape(struct seq_file *m, const char *s, const char *esc)
317 {
318         char *end = m->buf + m->size;
319         char *p;
320         char c;
321
322         for (p = m->buf + m->count; (c = *s) != '\0' && p < end; s++) {
323                 if (!strchr(esc, c)) {
324                         *p++ = c;
325                         continue;
326                 }
327                 if (p + 3 < end) {
328                         *p++ = '\\';
329                         *p++ = '0' + ((c & 0300) >> 6);
330                         *p++ = '0' + ((c & 070) >> 3);
331                         *p++ = '0' + (c & 07);
332                         continue;
333                 }
334                 m->count = m->size;
335                 return -1;
336         }
337         m->count = p - m->buf;
338         return 0;
339 }
340 EXPORT_SYMBOL(seq_escape);
341
342 int seq_printf(struct seq_file *m, const char *f, ...)
343 {
344         va_list args;
345         int len;
346
347         if (m->count < m->size) {
348                 va_start(args, f);
349                 len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
350                 va_end(args);
351                 if (m->count + len < m->size) {
352                         m->count += len;
353                         return 0;
354                 }
355         }
356         m->count = m->size;
357         return -1;
358 }
359 EXPORT_SYMBOL(seq_printf);
360
361 /**
362  *      mangle_path -   mangle and copy path to buffer beginning
363  *      @s: buffer start
364  *      @p: beginning of path in above buffer
365  *      @esc: set of characters that need escaping
366  *
367  *      Copy the path from @p to @s, replacing each occurrence of character from
368  *      @esc with usual octal escape.
369  *      Returns pointer past last written character in @s, or NULL in case of
370  *      failure.
371  */
372 char *mangle_path(char *s, char *p, char *esc)
373 {
374         while (s <= p) {
375                 char c = *p++;
376                 if (!c) {
377                         return s;
378                 } else if (!strchr(esc, c)) {
379                         *s++ = c;
380                 } else if (s + 4 > p) {
381                         break;
382                 } else {
383                         *s++ = '\\';
384                         *s++ = '0' + ((c & 0300) >> 6);
385                         *s++ = '0' + ((c & 070) >> 3);
386                         *s++ = '0' + (c & 07);
387                 }
388         }
389         return NULL;
390 }
391 EXPORT_SYMBOL(mangle_path);
392
393 /**
394  * seq_path - seq_file interface to print a pathname
395  * @m: the seq_file handle
396  * @path: the struct path to print
397  * @esc: set of characters to escape in the output
398  *
399  * return the absolute path of 'path', as represented by the
400  * dentry / mnt pair in the path parameter.
401  */
402 int seq_path(struct seq_file *m, struct path *path, char *esc)
403 {
404         if (m->count < m->size) {
405                 char *s = m->buf + m->count;
406                 char *p = d_path(path, s, m->size - m->count);
407                 if (!IS_ERR(p)) {
408                         s = mangle_path(s, p, esc);
409                         if (s) {
410                                 p = m->buf + m->count;
411                                 m->count = s - m->buf;
412                                 return s - p;
413                         }
414                 }
415         }
416         m->count = m->size;
417         return -1;
418 }
419 EXPORT_SYMBOL(seq_path);
420
421 /*
422  * Same as seq_path, but relative to supplied root.
423  *
424  * root may be changed, see __d_path().
425  */
426 int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
427                   char *esc)
428 {
429         int err = -ENAMETOOLONG;
430         if (m->count < m->size) {
431                 char *s = m->buf + m->count;
432                 char *p;
433
434                 spin_lock(&dcache_lock);
435                 p = __d_path(path, root, s, m->size - m->count);
436                 spin_unlock(&dcache_lock);
437                 err = PTR_ERR(p);
438                 if (!IS_ERR(p)) {
439                         s = mangle_path(s, p, esc);
440                         if (s) {
441                                 p = m->buf + m->count;
442                                 m->count = s - m->buf;
443                                 return 0;
444                         }
445                 }
446         }
447         m->count = m->size;
448         return err;
449 }
450
451 /*
452  * returns the path of the 'dentry' from the root of its filesystem.
453  */
454 int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
455 {
456         if (m->count < m->size) {
457                 char *s = m->buf + m->count;
458                 char *p = dentry_path(dentry, s, m->size - m->count);
459                 if (!IS_ERR(p)) {
460                         s = mangle_path(s, p, esc);
461                         if (s) {
462                                 p = m->buf + m->count;
463                                 m->count = s - m->buf;
464                                 return s - p;
465                         }
466                 }
467         }
468         m->count = m->size;
469         return -1;
470 }
471
472 int seq_bitmap(struct seq_file *m, const unsigned long *bits,
473                                    unsigned int nr_bits)
474 {
475         if (m->count < m->size) {
476                 int len = bitmap_scnprintf(m->buf + m->count,
477                                 m->size - m->count, bits, nr_bits);
478                 if (m->count + len < m->size) {
479                         m->count += len;
480                         return 0;
481                 }
482         }
483         m->count = m->size;
484         return -1;
485 }
486 EXPORT_SYMBOL(seq_bitmap);
487
488 int seq_bitmap_list(struct seq_file *m, unsigned long *bits,
489                 unsigned int nr_bits)
490 {
491         if (m->count < m->size) {
492                 int len = bitmap_scnlistprintf(m->buf + m->count,
493                                 m->size - m->count, bits, nr_bits);
494                 if (m->count + len < m->size) {
495                         m->count += len;
496                         return 0;
497                 }
498         }
499         m->count = m->size;
500         return -1;
501 }
502 EXPORT_SYMBOL(seq_bitmap_list);
503
504 static void *single_start(struct seq_file *p, loff_t *pos)
505 {
506         return NULL + (*pos == 0);
507 }
508
509 static void *single_next(struct seq_file *p, void *v, loff_t *pos)
510 {
511         ++*pos;
512         return NULL;
513 }
514
515 static void single_stop(struct seq_file *p, void *v)
516 {
517 }
518
519 int single_open(struct file *file, int (*show)(struct seq_file *, void *),
520                 void *data)
521 {
522         struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL);
523         int res = -ENOMEM;
524
525         if (op) {
526                 op->start = single_start;
527                 op->next = single_next;
528                 op->stop = single_stop;
529                 op->show = show;
530                 res = seq_open(file, op);
531                 if (!res)
532                         ((struct seq_file *)file->private_data)->private = data;
533                 else
534                         kfree(op);
535         }
536         return res;
537 }
538 EXPORT_SYMBOL(single_open);
539
540 int single_release(struct inode *inode, struct file *file)
541 {
542         const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
543         int res = seq_release(inode, file);
544         kfree(op);
545         return res;
546 }
547 EXPORT_SYMBOL(single_release);
548
549 int seq_release_private(struct inode *inode, struct file *file)
550 {
551         struct seq_file *seq = file->private_data;
552
553         kfree(seq->private);
554         seq->private = NULL;
555         return seq_release(inode, file);
556 }
557 EXPORT_SYMBOL(seq_release_private);
558
559 void *__seq_open_private(struct file *f, const struct seq_operations *ops,
560                 int psize)
561 {
562         int rc;
563         void *private;
564         struct seq_file *seq;
565
566         private = kzalloc(psize, GFP_KERNEL);
567         if (private == NULL)
568                 goto out;
569
570         rc = seq_open(f, ops);
571         if (rc < 0)
572                 goto out_free;
573
574         seq = f->private_data;
575         seq->private = private;
576         return private;
577
578 out_free:
579         kfree(private);
580 out:
581         return NULL;
582 }
583 EXPORT_SYMBOL(__seq_open_private);
584
585 int seq_open_private(struct file *filp, const struct seq_operations *ops,
586                 int psize)
587 {
588         return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
589 }
590 EXPORT_SYMBOL(seq_open_private);
591
592 int seq_putc(struct seq_file *m, char c)
593 {
594         if (m->count < m->size) {
595                 m->buf[m->count++] = c;
596                 return 0;
597         }
598         return -1;
599 }
600 EXPORT_SYMBOL(seq_putc);
601
602 int seq_puts(struct seq_file *m, const char *s)
603 {
604         int len = strlen(s);
605         if (m->count + len < m->size) {
606                 memcpy(m->buf + m->count, s, len);
607                 m->count += len;
608                 return 0;
609         }
610         m->count = m->size;
611         return -1;
612 }
613 EXPORT_SYMBOL(seq_puts);
614
615 struct list_head *seq_list_start(struct list_head *head, loff_t pos)
616 {
617         struct list_head *lh;
618
619         list_for_each(lh, head)
620                 if (pos-- == 0)
621                         return lh;
622
623         return NULL;
624 }
625
626 EXPORT_SYMBOL(seq_list_start);
627
628 struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
629 {
630         if (!pos)
631                 return head;
632
633         return seq_list_start(head, pos - 1);
634 }
635
636 EXPORT_SYMBOL(seq_list_start_head);
637
638 struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
639 {
640         struct list_head *lh;
641
642         lh = ((struct list_head *)v)->next;
643         ++*ppos;
644         return lh == head ? NULL : lh;
645 }
646
647 EXPORT_SYMBOL(seq_list_next);