symlink.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * symlink.c
  3.  *
  4.  * PURPOSE
  5.  * Symlink handling routines for the OSTA-UDF(tm) filesystem.
  6.  *
  7.  * CONTACTS
  8.  * E-mail regarding any portion of the Linux UDF file system should be
  9.  * directed to the development team mailing list (run by majordomo):
  10.  * linux_udf@hpesjro.fc.hp.com
  11.  *
  12.  * COPYRIGHT
  13.  * This file is distributed under the terms of the GNU General Public
  14.  * License (GPL). Copies of the GPL can be obtained from:
  15.  * ftp://prep.ai.mit.edu/pub/gnu/GPL
  16.  * Each contributing author retains all rights to their own work.
  17.  *
  18.  *  (C) 1998-2000 Ben Fennema
  19.  *  (C) 1999 Stelias Computing Inc 
  20.  *
  21.  * HISTORY
  22.  *
  23.  *  04/16/99 blf  Created.
  24.  *
  25.  */
  26. #include "udfdecl.h"
  27. #include <asm/uaccess.h>
  28. #include <linux/errno.h>
  29. #include <linux/fs.h>
  30. #include <linux/udf_fs.h>
  31. #include <linux/sched.h>
  32. #include <linux/mm.h>
  33. #include <linux/stat.h>
  34. #include <linux/slab.h>
  35. #include <linux/pagemap.h>
  36. #include <linux/smp_lock.h>
  37. #include "udf_i.h"
  38. static void udf_pc_to_char(char *from, int fromlen, char *to)
  39. {
  40. struct PathComponent *pc;
  41. int elen = 0;
  42. char *p = to;
  43. while (elen < fromlen)
  44. {
  45. pc = (struct PathComponent *)(from + elen);
  46. switch (pc->componentType)
  47. {
  48. case 1:
  49. if (pc->lengthComponentIdent == 0)
  50. {
  51. p = to;
  52. *p++ = '/';
  53. }
  54. break;
  55. case 3:
  56. memcpy(p, "../", 3);
  57. p += 3;
  58. break;
  59. case 4:
  60. memcpy(p, "./", 2);
  61. p += 2;
  62. /* that would be . - just ignore */
  63. break;
  64. case 5:
  65. memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
  66. p += pc->lengthComponentIdent;
  67. *p++ = '/';
  68. }
  69. elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
  70. }
  71. if (p > to+1)
  72. p[-1] = '';
  73. else
  74. p[0] = '';
  75. }
  76. static int udf_symlink_filler(struct file *file, struct page *page)
  77. {
  78. struct inode *inode = page->mapping->host;
  79. struct buffer_head *bh = NULL;
  80. char *symlink;
  81. int err = -EIO;
  82. char *p = kmap(page);
  83. lock_kernel();
  84. if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
  85. {
  86. bh = udf_tread(inode->i_sb, inode->i_ino);
  87. if (!bh)
  88. goto out;
  89. symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
  90. }
  91. else
  92. {
  93. bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
  94. if (!bh)
  95. goto out;
  96. symlink = bh->b_data;
  97. }
  98. udf_pc_to_char(symlink, inode->i_size, p);
  99. udf_release_data(bh);
  100. unlock_kernel();
  101. SetPageUptodate(page);
  102. kunmap(page);
  103. UnlockPage(page);
  104. return 0;
  105. out:
  106. unlock_kernel();
  107. SetPageError(page);
  108. kunmap(page);
  109. UnlockPage(page);
  110. return err;
  111. }
  112. /*
  113.  * symlinks can't do much...
  114.  */
  115. struct address_space_operations udf_symlink_aops = {
  116. readpage: udf_symlink_filler,
  117. };