symlink.c 4.3 KB

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