namei.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. if ((foundinode = iget(dir->i_sb, ino)) == NULL) {
  123. unlock_kernel();
  124. QNX4DEBUG(("qnx4: lookup->iget -> NULL\n"));
  125. return ERR_PTR(-EACCES);
  126. }
  127. out:
  128. unlock_kernel();
  129. d_add(dentry, foundinode);
  130. return NULL;
  131. }
  132. #ifdef CONFIG_QNX4FS_RW
  133. int qnx4_create(struct inode *dir, struct dentry *dentry, int mode,
  134. struct nameidata *nd)
  135. {
  136. QNX4DEBUG(("qnx4: qnx4_create\n"));
  137. if (dir == NULL) {
  138. return -ENOENT;
  139. }
  140. return -ENOSPC;
  141. }
  142. int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
  143. {
  144. struct buffer_head *bh;
  145. struct qnx4_inode_entry *de;
  146. struct inode *inode;
  147. int retval;
  148. int ino;
  149. QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
  150. lock_kernel();
  151. bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  152. &de, &ino);
  153. if (bh == NULL) {
  154. unlock_kernel();
  155. return -ENOENT;
  156. }
  157. inode = dentry->d_inode;
  158. if (inode->i_ino != ino) {
  159. retval = -EIO;
  160. goto end_rmdir;
  161. }
  162. #if 0
  163. if (!empty_dir(inode)) {
  164. retval = -ENOTEMPTY;
  165. goto end_rmdir;
  166. }
  167. #endif
  168. if (inode->i_nlink != 2) {
  169. QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
  170. }
  171. QNX4DEBUG(("qnx4: deleting directory\n"));
  172. de->di_status = 0;
  173. memset(de->di_fname, 0, sizeof de->di_fname);
  174. de->di_mode = 0;
  175. mark_buffer_dirty(bh);
  176. clear_nlink(inode);
  177. mark_inode_dirty(inode);
  178. inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
  179. inode_dec_link_count(dir);
  180. retval = 0;
  181. end_rmdir:
  182. brelse(bh);
  183. unlock_kernel();
  184. return retval;
  185. }
  186. int qnx4_unlink(struct inode *dir, struct dentry *dentry)
  187. {
  188. struct buffer_head *bh;
  189. struct qnx4_inode_entry *de;
  190. struct inode *inode;
  191. int retval;
  192. int ino;
  193. QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name));
  194. lock_kernel();
  195. bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  196. &de, &ino);
  197. if (bh == NULL) {
  198. unlock_kernel();
  199. return -ENOENT;
  200. }
  201. inode = dentry->d_inode;
  202. if (inode->i_ino != ino) {
  203. retval = -EIO;
  204. goto end_unlink;
  205. }
  206. retval = -EPERM;
  207. if (!inode->i_nlink) {
  208. QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
  209. inode->i_sb->s_id,
  210. inode->i_ino, inode->i_nlink));
  211. inode->i_nlink = 1;
  212. }
  213. de->di_status = 0;
  214. memset(de->di_fname, 0, sizeof de->di_fname);
  215. de->di_mode = 0;
  216. mark_buffer_dirty(bh);
  217. dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
  218. mark_inode_dirty(dir);
  219. inode->i_ctime = dir->i_ctime;
  220. inode_dec_link_count(inode);
  221. retval = 0;
  222. end_unlink:
  223. unlock_kernel();
  224. brelse(bh);
  225. return retval;
  226. }
  227. #endif