symlink.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * linux/fs/affs/symlink.c
  3. *
  4. * 1995 Hans-Joachim Widmaier - Modified for affs.
  5. *
  6. * Copyright (C) 1991, 1992 Linus Torvalds
  7. *
  8. * affs symlink handling code
  9. */
  10. #include "affs.h"
  11. static int affs_symlink_readpage(struct file *file, struct page *page)
  12. {
  13. struct buffer_head *bh;
  14. struct inode *inode = page->mapping->host;
  15. char *link = kmap(page);
  16. struct slink_front *lf;
  17. int i, j;
  18. char c;
  19. char lc;
  20. pr_debug("follow_link(ino=%lu)\n", inode->i_ino);
  21. bh = affs_bread(inode->i_sb, inode->i_ino);
  22. if (!bh)
  23. goto fail;
  24. i = 0;
  25. j = 0;
  26. lf = (struct slink_front *)bh->b_data;
  27. lc = 0;
  28. if (strchr(lf->symname,':')) { /* Handle assign or volume name */
  29. struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
  30. char *pf;
  31. spin_lock(&sbi->symlink_lock);
  32. pf = sbi->s_prefix ? sbi->s_prefix : "/";
  33. while (i < 1023 && (c = pf[i]))
  34. link[i++] = c;
  35. spin_unlock(&sbi->symlink_lock);
  36. while (i < 1023 && lf->symname[j] != ':')
  37. link[i++] = lf->symname[j++];
  38. if (i < 1023)
  39. link[i++] = '/';
  40. j++;
  41. lc = '/';
  42. }
  43. while (i < 1023 && (c = lf->symname[j])) {
  44. if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
  45. link[i++] = '.';
  46. link[i++] = '.';
  47. }
  48. link[i++] = c;
  49. lc = c;
  50. j++;
  51. }
  52. link[i] = '\0';
  53. affs_brelse(bh);
  54. SetPageUptodate(page);
  55. kunmap(page);
  56. unlock_page(page);
  57. return 0;
  58. fail:
  59. SetPageError(page);
  60. kunmap(page);
  61. unlock_page(page);
  62. return -EIO;
  63. }
  64. const struct address_space_operations affs_symlink_aops = {
  65. .readpage = affs_symlink_readpage,
  66. };
  67. const struct inode_operations affs_symlink_inode_operations = {
  68. .readlink = generic_readlink,
  69. .follow_link = page_follow_link_light,
  70. .put_link = page_put_link,
  71. .setattr = affs_notify_change,
  72. };