symlink.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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 = page_address(page);
  16. struct slink_front *lf;
  17. int i, j;
  18. char c;
  19. char lc;
  20. pr_debug("get_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. unlock_page(page);
  56. return 0;
  57. fail:
  58. SetPageError(page);
  59. unlock_page(page);
  60. return -EIO;
  61. }
  62. const struct address_space_operations affs_symlink_aops = {
  63. .readpage = affs_symlink_readpage,
  64. };
  65. const struct inode_operations affs_symlink_inode_operations = {
  66. .readlink = generic_readlink,
  67. .get_link = page_get_link,
  68. .setattr = affs_notify_change,
  69. };