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