symlink.c 1.6 KB

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