symlink.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * symlink.c
  4. *
  5. * PURPOSE
  6. * Symlink handling routines for the OSTA-UDF(tm) filesystem.
  7. *
  8. * COPYRIGHT
  9. * (C) 1998-2001 Ben Fennema
  10. * (C) 1999 Stelias Computing Inc
  11. *
  12. * HISTORY
  13. *
  14. * 04/16/99 blf Created.
  15. *
  16. */
  17. #include "udfdecl.h"
  18. #include <linux/uaccess.h>
  19. #include <linux/errno.h>
  20. #include <linux/fs.h>
  21. #include <linux/time.h>
  22. #include <linux/mm.h>
  23. #include <linux/stat.h>
  24. #include <linux/pagemap.h>
  25. #include "udf_i.h"
  26. static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
  27. int fromlen, unsigned char *to, int tolen)
  28. {
  29. struct pathComponent *pc;
  30. int elen = 0;
  31. int comp_len;
  32. unsigned char *p = to;
  33. /* Reserve one byte for terminating \0 */
  34. tolen--;
  35. while (elen < fromlen) {
  36. pc = (struct pathComponent *)(from + elen);
  37. elen += sizeof(struct pathComponent);
  38. switch (pc->componentType) {
  39. case 1:
  40. /*
  41. * Symlink points to some place which should be agreed
  42. * upon between originator and receiver of the media. Ignore.
  43. */
  44. if (pc->lengthComponentIdent > 0) {
  45. elen += pc->lengthComponentIdent;
  46. break;
  47. }
  48. fallthrough;
  49. case 2:
  50. if (tolen == 0)
  51. return -ENAMETOOLONG;
  52. p = to;
  53. *p++ = '/';
  54. tolen--;
  55. break;
  56. case 3:
  57. if (tolen < 3)
  58. return -ENAMETOOLONG;
  59. memcpy(p, "../", 3);
  60. p += 3;
  61. tolen -= 3;
  62. break;
  63. case 4:
  64. if (tolen < 2)
  65. return -ENAMETOOLONG;
  66. memcpy(p, "./", 2);
  67. p += 2;
  68. tolen -= 2;
  69. /* that would be . - just ignore */
  70. break;
  71. case 5:
  72. elen += pc->lengthComponentIdent;
  73. if (elen > fromlen)
  74. return -EIO;
  75. comp_len = udf_get_filename(sb, pc->componentIdent,
  76. pc->lengthComponentIdent,
  77. p, tolen);
  78. if (comp_len < 0)
  79. return comp_len;
  80. p += comp_len;
  81. tolen -= comp_len;
  82. if (tolen == 0)
  83. return -ENAMETOOLONG;
  84. *p++ = '/';
  85. tolen--;
  86. break;
  87. }
  88. }
  89. if (p > to + 1)
  90. p[-1] = '\0';
  91. else
  92. p[0] = '\0';
  93. return 0;
  94. }
  95. static int udf_symlink_filler(struct file *file, struct folio *folio)
  96. {
  97. struct inode *inode = folio->mapping->host;
  98. struct buffer_head *bh = NULL;
  99. unsigned char *symlink;
  100. int err = 0;
  101. unsigned char *p = folio_address(folio);
  102. struct udf_inode_info *iinfo = UDF_I(inode);
  103. /* We don't support symlinks longer than one block */
  104. if (inode->i_size > inode->i_sb->s_blocksize) {
  105. err = -ENAMETOOLONG;
  106. goto out;
  107. }
  108. if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  109. symlink = iinfo->i_data + iinfo->i_lenEAttr;
  110. } else {
  111. bh = udf_bread(inode, 0, 0, &err);
  112. if (!bh) {
  113. if (!err)
  114. err = -EFSCORRUPTED;
  115. goto out;
  116. }
  117. symlink = bh->b_data;
  118. }
  119. err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
  120. brelse(bh);
  121. out:
  122. folio_end_read(folio, err == 0);
  123. return err;
  124. }
  125. static int udf_symlink_getattr(struct mnt_idmap *idmap,
  126. const struct path *path, struct kstat *stat,
  127. u32 request_mask, unsigned int flags)
  128. {
  129. struct dentry *dentry = path->dentry;
  130. struct inode *inode = d_backing_inode(dentry);
  131. struct folio *folio;
  132. generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
  133. folio = read_mapping_folio(inode->i_mapping, 0, NULL);
  134. if (IS_ERR(folio))
  135. return PTR_ERR(folio);
  136. /*
  137. * UDF uses non-trivial encoding of symlinks so i_size does not match
  138. * number of characters reported by readlink(2) which apparently some
  139. * applications expect. Also POSIX says that "The value returned in the
  140. * st_size field shall be the length of the contents of the symbolic
  141. * link, and shall not count a trailing null if one is present." So
  142. * let's report the length of string returned by readlink(2) for
  143. * st_size.
  144. */
  145. stat->size = strlen(folio_address(folio));
  146. folio_put(folio);
  147. return 0;
  148. }
  149. /*
  150. * symlinks can't do much...
  151. */
  152. const struct address_space_operations udf_symlink_aops = {
  153. .read_folio = udf_symlink_filler,
  154. };
  155. const struct inode_operations udf_symlink_inode_operations = {
  156. .get_link = page_get_link,
  157. .getattr = udf_symlink_getattr,
  158. };