namei.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * QNX4 file system, Linux implementation.
  3. *
  4. * Version : 0.2.1
  5. *
  6. * Using parts of the xiafs filesystem.
  7. *
  8. * History :
  9. *
  10. * 01-06-1998 by Richard Frowijn : first release.
  11. * 21-06-1998 by Frank Denis : dcache support, fixed error codes.
  12. * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
  13. */
  14. #include <linux/time.h>
  15. #include <linux/fs.h>
  16. #include <linux/qnx4_fs.h>
  17. #include <linux/kernel.h>
  18. #include <linux/string.h>
  19. #include <linux/stat.h>
  20. #include <linux/fcntl.h>
  21. #include <linux/errno.h>
  22. #include <linux/smp_lock.h>
  23. #include <linux/buffer_head.h>
  24. /*
  25. * check if the filename is correct. For some obscure reason, qnx writes a
  26. * new file twice in the directory entry, first with all possible options at 0
  27. * and for a second time the way it is, they want us not to access the qnx
  28. * filesystem when whe are using linux.
  29. */
  30. static int qnx4_match(int len, const char *name,
  31. struct buffer_head *bh, unsigned long *offset)
  32. {
  33. struct qnx4_inode_entry *de;
  34. int namelen, thislen;
  35. if (bh == NULL) {
  36. printk("qnx4: matching unassigned buffer !\n");
  37. return 0;
  38. }
  39. de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
  40. *offset += QNX4_DIR_ENTRY_SIZE;
  41. if ((de->di_status & QNX4_FILE_LINK) != 0) {
  42. namelen = QNX4_NAME_MAX;
  43. } else {
  44. namelen = QNX4_SHORT_NAME_MAX;
  45. }
  46. /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
  47. if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
  48. return 1;
  49. }
  50. thislen = strlen( de->di_fname );
  51. if ( thislen > namelen )
  52. thislen = namelen;
  53. if (len != thislen) {
  54. return 0;
  55. }
  56. if (strncmp(name, de->di_fname, len) == 0) {
  57. if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
  58. return 1;
  59. }
  60. }
  61. return 0;
  62. }
  63. static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
  64. const char *name, struct qnx4_inode_entry **res_dir, int *ino)
  65. {
  66. unsigned long block, offset, blkofs;
  67. struct buffer_head *bh;
  68. *res_dir = NULL;
  69. if (!dir->i_sb) {
  70. printk("qnx4: no superblock on dir.\n");
  71. return NULL;
  72. }
  73. bh = NULL;
  74. block = offset = blkofs = 0;
  75. while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
  76. if (!bh) {
  77. bh = qnx4_bread(dir, blkofs, 0);
  78. if (!bh) {
  79. blkofs++;
  80. continue;
  81. }
  82. }
  83. *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
  84. if (qnx4_match(len, name, bh, &offset)) {
  85. block = qnx4_block_map( dir, blkofs );
  86. *ino = block * QNX4_INODES_PER_BLOCK +
  87. (offset / QNX4_DIR_ENTRY_SIZE) - 1;
  88. return bh;
  89. }
  90. if (offset < bh->b_size) {
  91. continue;
  92. }
  93. brelse(bh);
  94. bh = NULL;
  95. offset = 0;
  96. blkofs++;
  97. }
  98. brelse(bh);
  99. *res_dir = NULL;
  100. return NULL;
  101. }
  102. struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  103. {
  104. int ino;
  105. struct qnx4_inode_entry *de;
  106. struct qnx4_link_info *lnk;
  107. struct buffer_head *bh;
  108. const char *name = dentry->d_name.name;
  109. int len = dentry->d_name.len;
  110. struct inode *foundinode = NULL;
  111. lock_kernel();
  112. if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
  113. goto out;
  114. /* The entry is linked, let's get the real info */
  115. if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) {
  116. lnk = (struct qnx4_link_info *) de;
  117. ino = (le32_to_cpu(lnk->dl_inode_blk) - 1) *
  118. QNX4_INODES_PER_BLOCK +
  119. lnk->dl_inode_ndx;
  120. }
  121. brelse(bh);
  122. foundinode = qnx4_iget(dir->i_sb, ino);
  123. if (IS_ERR(foundinode)) {
  124. unlock_kernel();
  125. QNX4DEBUG(("qnx4: lookup->iget -> error %ld\n",
  126. PTR_ERR(foundinode)));
  127. return ERR_CAST(foundinode);
  128. }
  129. out:
  130. unlock_kernel();
  131. d_add(dentry, foundinode);
  132. return NULL;
  133. }
  134. #ifdef CONFIG_QNX4FS_RW
  135. int qnx4_create(struct inode *dir, struct dentry *dentry, int mode,
  136. struct nameidata *nd)
  137. {
  138. QNX4DEBUG(("qnx4: qnx4_create\n"));
  139. if (dir == NULL) {
  140. return -ENOENT;
  141. }
  142. return -ENOSPC;
  143. }
  144. int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
  145. {
  146. struct buffer_head *bh;
  147. struct qnx4_inode_entry *de;
  148. struct inode *inode;
  149. int retval;
  150. int ino;
  151. QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
  152. lock_kernel();
  153. bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  154. &de, &ino);
  155. if (bh == NULL) {
  156. unlock_kernel();
  157. return -ENOENT;
  158. }
  159. inode = dentry->d_inode;
  160. if (inode->i_ino != ino) {
  161. retval = -EIO;
  162. goto end_rmdir;
  163. }
  164. #if 0
  165. if (!empty_dir(inode)) {
  166. retval = -ENOTEMPTY;
  167. goto end_rmdir;
  168. }
  169. #endif
  170. if (inode->i_nlink != 2) {
  171. QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
  172. }
  173. QNX4DEBUG(("qnx4: deleting directory\n"));
  174. de->di_status = 0;
  175. memset(de->di_fname, 0, sizeof de->di_fname);
  176. de->di_mode = 0;
  177. mark_buffer_dirty(bh);
  178. clear_nlink(inode);
  179. mark_inode_dirty(inode);
  180. inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
  181. inode_dec_link_count(dir);
  182. retval = 0;
  183. end_rmdir:
  184. brelse(bh);
  185. unlock_kernel();
  186. return retval;
  187. }
  188. int qnx4_unlink(struct inode *dir, struct dentry *dentry)
  189. {
  190. struct buffer_head *bh;
  191. struct qnx4_inode_entry *de;
  192. struct inode *inode;
  193. int retval;
  194. int ino;
  195. QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name));
  196. lock_kernel();
  197. bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  198. &de, &ino);
  199. if (bh == NULL) {
  200. unlock_kernel();
  201. return -ENOENT;
  202. }
  203. inode = dentry->d_inode;
  204. if (inode->i_ino != ino) {
  205. retval = -EIO;
  206. goto end_unlink;
  207. }
  208. retval = -EPERM;
  209. if (!inode->i_nlink) {
  210. QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
  211. inode->i_sb->s_id,
  212. inode->i_ino, inode->i_nlink));
  213. inode->i_nlink = 1;
  214. }
  215. de->di_status = 0;
  216. memset(de->di_fname, 0, sizeof de->di_fname);
  217. de->di_mode = 0;
  218. mark_buffer_dirty(bh);
  219. dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
  220. mark_inode_dirty(dir);
  221. inode->i_ctime = dir->i_ctime;
  222. inode_dec_link_count(inode);
  223. retval = 0;
  224. end_unlink:
  225. unlock_kernel();
  226. brelse(bh);
  227. return retval;
  228. }
  229. #endif