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); 648