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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/isofs/namei.c
  3.  *
  4.  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  5.  *
  6.  *  (C) 1991  Linus Torvalds - minix filesystem
  7.  */
  8. #include <linux/sched.h>
  9. #include <linux/iso_fs.h>
  10. #include <linux/kernel.h>
  11. #include <linux/string.h>
  12. #include <linux/stat.h>
  13. #include <linux/fcntl.h>
  14. #include <linux/slab.h>
  15. #include <linux/errno.h>
  16. #include <linux/config.h> /* Joliet? */
  17. #include <asm/uaccess.h>
  18. /*
  19.  * ok, we cannot use strncmp, as the name is not in our data space.
  20.  * Thus we'll have to use isofs_match. No big problem. Match also makes
  21.  * some sanity tests.
  22.  */
  23. static int
  24. isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
  25. {
  26. struct qstr qstr;
  27. if (!compare)
  28. return 1;
  29. /* check special "." and ".." files */
  30. if (dlen == 1) {
  31. /* "." */
  32. if (compare[0] == 0) {
  33. if (!dentry->d_name.len)
  34. return 0;
  35. compare = ".";
  36. } else if (compare[0] == 1) {
  37. compare = "..";
  38. dlen = 2;
  39. }
  40. }
  41. qstr.name = compare;
  42. qstr.len = dlen;
  43. return dentry->d_op->d_compare(dentry, &dentry->d_name, &qstr);
  44. }
  45. /*
  46.  * isofs_find_entry()
  47.  *
  48.  * finds an entry in the specified directory with the wanted name. It
  49.  * returns the inode number of the found entry, or 0 on error.
  50.  */
  51. static unsigned long
  52. isofs_find_entry(struct inode *dir, struct dentry *dentry,
  53. char * tmpname, struct iso_directory_record * tmpde)
  54. {
  55. unsigned long inode_number;
  56. unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
  57. unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
  58. unsigned int block, f_pos, offset;
  59. struct buffer_head * bh = NULL;
  60. if (!dir->u.isofs_i.i_first_extent)
  61. return 0;
  62.   
  63. f_pos = 0;
  64. offset = 0;
  65. block = 0;
  66. while (f_pos < dir->i_size) {
  67. struct iso_directory_record * de;
  68. int de_len, match, i, dlen;
  69. char *dpnt;
  70. if (!bh) {
  71. bh = isofs_bread(dir, block);
  72. if (!bh)
  73. return 0;
  74. }
  75. de = (struct iso_directory_record *) (bh->b_data + offset);
  76. inode_number = (bh->b_blocknr << bufbits) + offset;
  77. de_len = *(unsigned char *) de;
  78. if (!de_len) {
  79. brelse(bh);
  80. bh = NULL;
  81. f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
  82. block = f_pos >> bufbits;
  83. offset = 0;
  84. continue;
  85. }
  86. offset += de_len;
  87. f_pos += de_len;
  88. /* Make sure we have a full directory entry */
  89. if (offset >= bufsize) {
  90. int slop = bufsize - offset + de_len;
  91. memcpy(tmpde, de, slop);
  92. offset &= bufsize - 1;
  93. block++;
  94. brelse(bh);
  95. bh = NULL;
  96. if (offset) {
  97. bh = isofs_bread(dir, block);
  98. if (!bh)
  99. return 0;
  100. memcpy((void *) tmpde + slop, bh->b_data, offset);
  101. }
  102. de = tmpde;
  103. }
  104. dlen = de->name_len[0];
  105. dpnt = de->name;
  106. if (dir->i_sb->u.isofs_sb.s_rock &&
  107.     ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
  108. dlen = i;  /* possibly -1 */
  109. dpnt = tmpname;
  110. #ifdef CONFIG_JOLIET
  111. } else if (dir->i_sb->u.isofs_sb.s_joliet_level) {
  112. dlen = get_joliet_filename(de, tmpname, dir);
  113. dpnt = tmpname;
  114. #endif
  115. } else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') {
  116. dlen = get_acorn_filename(de, tmpname, dir);
  117. dpnt = tmpname;
  118. } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') {
  119. dlen = isofs_name_translate(de, tmpname, dir);
  120. dpnt = tmpname;
  121. }
  122. /*
  123.  * Skip hidden or associated files unless unhide is set 
  124.  */
  125. match = 0;
  126. if (dlen > 0 &&
  127.     (!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)
  128.      || dir->i_sb->u.isofs_sb.s_unhide == 'y'))
  129. {
  130. match = (isofs_cmp(dentry,dpnt,dlen) == 0);
  131. }
  132. if (match) {
  133. if (bh) brelse(bh);
  134. return inode_number;
  135. }
  136. }
  137. if (bh) brelse(bh);
  138. return 0;
  139. }
  140. struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry)
  141. {
  142. unsigned long ino;
  143. struct inode *inode;
  144. struct page *page;
  145. dentry->d_op = dir->i_sb->s_root->d_op;
  146. page = alloc_page(GFP_USER);
  147. if (!page)
  148. return ERR_PTR(-ENOMEM);
  149. ino = isofs_find_entry(dir, dentry, page_address(page),
  150.        1024 + page_address(page));
  151. __free_page(page);
  152. inode = NULL;
  153. if (ino) {
  154. inode = iget(dir->i_sb, ino);
  155. if (!inode)
  156. return ERR_PTR(-EACCES);
  157. }
  158. d_add(dentry, inode);
  159. return NULL;
  160. }