1 /* 2 * linux/fs/affs/namei.c 3 * 4 * (c) 1996 Hans-Joachim Widmaier - Rewritten 5 * 6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. 7 * 8 * (C) 1991 Linus Torvalds - minix filesystem 9 */ 10 11 #include "affs.h" 12 13 typedef int (*toupper_t)(int); 14 15 static int affs_toupper(int ch); 16 static int affs_hash_dentry(struct dentry *, struct qstr *); 17 static int affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 18 static int affs_intl_toupper(int ch); 19 static int affs_intl_hash_dentry(struct dentry *, struct qstr *); 20 static int affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 21 22 const struct dentry_operations affs_dentry_operations = { 23 .d_hash = affs_hash_dentry, 24 .d_compare = affs_compare_dentry, 25 }; 26 27 static const struct dentry_operations affs_intl_dentry_operations = { 28 .d_hash = affs_intl_hash_dentry, 29 .d_compare = affs_intl_compare_dentry, 30 }; 31 32 33 /* Simple toupper() for DOS\1 */ 34 35 static int 36 affs_toupper(int ch) 37 { 38 return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch; 39 } 40 41 /* International toupper() for DOS\3 ("international") */ 42 43 static int 44 affs_intl_toupper(int ch) 45 { 46 return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0 47 && ch <= 0xFE && ch != 0xF7) ? 48 ch - ('a' - 'A') : ch; 49 } 50 51 static inline toupper_t 52 affs_get_toupper(struct super_block *sb) 53 { 54 return AFFS_SB(sb)->s_flags & SF_INTL ? affs_intl_toupper : affs_toupper; 55 } 56 57 /* 58 * Note: the dentry argument is the parent dentry. 59 */ 60 static inline int 61 __affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper) 62 { 63 const u8 *name = qstr->name; 64 unsigned long hash; 65 int i; 66 67 i = affs_check_name(qstr->name,qstr->len); 68 if (i) 69 return i; 70 71 hash = init_name_hash(); 72 i = min(qstr->len, 30u); 73 for (; i > 0; name++, i--) 74 hash = partial_name_hash(toupper(*name), hash); 75 qstr->hash = end_name_hash(hash); 76 77 return 0; 78 } 79 80 static int 81 affs_hash_dentry(struct dentry *dentry, struct qstr *qstr) 82 { 83 return __affs_hash_dentry(dentry, qstr, affs_toupper); 84 } 85 static int 86 affs_intl_hash_dentry(struct dentry *dentry, struct qstr *qstr) 87 { 88 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper); 89 } 90 91 static inline int 92 __affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, toupper_t toupper) 93 { 94 const u8 *aname = a->name; 95 const u8 *bname = b->name; 96 int len; 97 98 /* 'a' is the qstr of an already existing dentry, so the name 99 * must be valid. 'b' must be validated first. 100 */ 101 102 if (affs_check_name(b->name,b->len)) 103 return 1; 104 105 /* If the names are longer than the allowed 30 chars, 106 * the excess is ignored, so their length may differ. 107 */ 108 len = a->len; 109 if (len >= 30) { 110 if (b->len < 30) 111 return 1; 112 len = 30; 113 } else if (len != b->len) 114 return 1; 115 116 for (; len > 0; len--) 117 if (toupper(*aname++) != toupper(*bname++)) 118 return 1; 119 120 return 0; 121 } 122 123 static int 124 affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 125 { 126 return __affs_compare_dentry(dentry, a, b, affs_toupper); 127 } 128 static int 129 affs_intl_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 130 { 131 return __affs_compare_dentry(dentry, a, b, affs_intl_toupper); 132 } 133 134 /* 135 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure. 136 */ 137 138 static inline int 139 affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) 140 { 141 const u8 *name = dentry->d_name.name; 142 int len = dentry->d_name.len; 143 144 if (len >= 30) { 145 if (*name2 < 30) 146 return 0; 147 len = 30; 148 } else if (len != *name2) 149 return 0; 150 151 for (name2++; len > 0; len--) 152 if (toupper(*name++) != toupper(*name2++)) 153 return 0; 154 return 1; 155 } 156 157 int 158 affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) 159 { 160 toupper_t toupper = affs_get_toupper(sb); 161 int hash; 162 163 hash = len = min(len, 30u); 164 for (; len > 0; len--) 165 hash = (hash * 13 + toupper(*name++)) & 0x7ff; 166 167 return hash % AFFS_SB(sb)->s_hashsize; 168 } 169 170 static struct buffer_head * 171 affs_find_entry(struct inode *dir, struct dentry *dentry) 172 { 173 struct super_block *sb = dir->i_sb; 174 struct buffer_head *bh; 175 toupper_t toupper = affs_get_toupper(sb); 176 u32 key; 177 178 pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name); 179 180 bh = affs_bread(sb, dir->i_ino); 181 if (!bh) 182 return ERR_PTR(-EIO); 183 184 key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]); 185 186 for (;;) { 187 affs_brelse(bh); 188 if (key == 0) 189 return NULL; 190 bh = affs_bread(sb, key); 191 if (!bh) 192 return ERR_PTR(-EIO); 193 if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper)) 194 return bh; 195 key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); 196 } 197 } 198 199 struct dentry * 200 affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 201 { 202 struct super_block *sb = dir->i_sb; 203 struct buffer_head *bh; 204 struct inode *inode = NULL; 205 206 pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name); 207 208 affs_lock_dir(dir); 209 bh = affs_find_entry(dir, dentry); 210 affs_unlock_dir(dir); 211 if (IS_ERR(bh)) 212 return ERR_CAST(bh); 213 if (bh) { 214 u32 ino = bh->b_blocknr; 215 216 /* store the real header ino in d_fsdata for faster lookups */ 217 dentry->d_fsdata = (void *)(long)ino; 218 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 219 //link to dirs disabled 220 //case ST_LINKDIR: 221 case ST_LINKFILE: 222 ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original); 223 } 224 affs_brelse(bh); 225 inode = affs_iget(sb, ino); 226 if (IS_ERR(inode)) 227 return ERR_PTR(PTR_ERR(inode)); 228 } 229 dentry->d_op = AFFS_SB(sb)->s_flags & SF_INTL ? &affs_intl_dentry_operations : &affs_dentry_operations; 230 d_add(dentry, inode); 231 return NULL; 232 } 233 234 int 235 affs_unlink(struct inode *dir, struct dentry *dentry) 236 { 237 pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino, 238 dentry->d_inode->i_ino, 239 (int)dentry->d_name.len, dentry->d_name.name); 240 241 return affs_remove_header(dentry); 242 } 243 244 int 245 affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) 246 { 247 struct super_block *sb = dir->i_sb; 248 struct inode *inode; 249 int error; 250 251 pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,(int)dentry->d_name.len, 252 dentry->d_name.name,mode); 253 254 inode = affs_new_inode(dir); 255 if (!inode) 256 return -ENOSPC; 257 258 inode->i_mode = mode; 259 mode_to_prot(inode); 260 mark_inode_dirty(inode); 261 262 inode->i_op = &affs_file_inode_operations; 263 inode->i_fop = &affs_file_operations; 264 inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; 265 error = affs_add_entry(dir, inode, dentry, ST_FILE); 266 if (error) { 267 inode->i_nlink = 0; 268 iput(inode); 269 return error; 270 } 271 return 0; 272 } 273 274 int 275 affs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 276 { 277 struct inode *inode; 278 int error; 279 280 pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir->i_ino, 281 (int)dentry->d_name.len,dentry->d_name.name,mode); 282 283 inode = affs_new_inode(dir); 284 if (!inode) 285 return -ENOSPC; 286 287 inode->i_mode = S_IFDIR | mode; 288 mode_to_prot(inode); 289 290 inode->i_op = &affs_dir_inode_operations; 291 inode->i_fop = &affs_dir_operations; 292 293 error = affs_add_entry(dir, inode, dentry, ST_USERDIR); 294 if (error) { 295 inode->i_nlink = 0; 296 mark_inode_dirty(inode); 297 iput(inode); 298 return error; 299 } 300 return 0; 301 } 302 303 int 304 affs_rmdir(struct inode *dir, struct dentry *dentry) 305 { 306 pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino, 307 dentry->d_inode->i_ino, 308 (int)dentry->d_name.len, dentry->d_name.name); 309 310 return affs_remove_header(dentry); 311 } 312 313 int 314 affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 315 { 316 struct super_block *sb = dir->i_sb; 317 struct buffer_head *bh; 318 struct inode *inode; 319 char *p; 320 int i, maxlen, error; 321 char c, lc; 322 323 pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino, 324 (int)dentry->d_name.len,dentry->d_name.name,symname); 325 326 maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; 327 inode = affs_new_inode(dir); 328 if (!inode) 329 return -ENOSPC; 330 331 inode->i_op = &affs_symlink_inode_operations; 332 inode->i_data.a_ops = &affs_symlink_aops; 333 inode->i_mode = S_IFLNK | 0777; 334 mode_to_prot(inode); 335 336 error = -EIO; 337 bh = affs_bread(sb, inode->i_ino); 338 if (!bh) 339 goto err; 340 i = 0; 341 p = (char *)AFFS_HEAD(bh)->table; 342 lc = '/'; 343 if (*symname == '/') { 344 while (*symname == '/') 345 symname++; 346 while (AFFS_SB(sb)->s_volume[i]) /* Cannot overflow */ 347 *p++ = AFFS_SB(sb)->s_volume[i++]; 348 } 349 while (i < maxlen && (c = *symname++)) { 350 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 351 *p++ = '/'; 352 i++; 353 symname += 2; 354 lc = '/'; 355 } else if (c == '.' && lc == '/' && *symname == '/') { 356 symname++; 357 lc = '/'; 358 } else { 359 *p++ = c; 360 lc = c; 361 i++; 362 } 363 if (lc == '/') 364 while (*symname == '/') 365 symname++; 366 } 367 *p = 0; 368 mark_buffer_dirty_inode(bh, inode); 369 affs_brelse(bh); 370 mark_inode_dirty(inode); 371 372 error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); 373 if (error) 374 goto err; 375 376 return 0; 377 378 err: 379 inode->i_nlink = 0; 380 mark_inode_dirty(inode); 381 iput(inode); 382 return error; 383 } 384 385 int 386 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 387 { 388 struct inode *inode = old_dentry->d_inode; 389 390 pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino, 391 (int)dentry->d_name.len,dentry->d_name.name); 392 393 return affs_add_entry(dir, inode, dentry, ST_LINKFILE); 394 } 395 396 int 397 affs_rename(struct inode *old_dir, struct dentry *old_dentry, 398 struct inode *new_dir, struct dentry *new_dentry) 399 { 400 struct super_block *sb = old_dir->i_sb; 401 struct buffer_head *bh = NULL; 402 int retval; 403 404 pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", 405 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, 406 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); 407 408 retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len); 409 if (retval) 410 return retval; 411 412 /* Unlink destination if it already exists */ 413 if (new_dentry->d_inode) { 414 retval = affs_remove_header(new_dentry); 415 if (retval) 416 return retval; 417 } 418 419 bh = affs_bread(sb, old_dentry->d_inode->i_ino); 420 if (!bh) 421 return -EIO; 422 423 /* Remove header from its parent directory. */ 424 affs_lock_dir(old_dir); 425 retval = affs_remove_hash(old_dir, bh); 426 affs_unlock_dir(old_dir); 427 if (retval) 428 goto done; 429 430 /* And insert it into the new directory with the new name. */ 431 affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); 432 affs_fix_checksum(sb, bh); 433 affs_lock_dir(new_dir); 434 retval = affs_insert_hash(new_dir, bh); 435 affs_unlock_dir(new_dir); 436 /* TODO: move it back to old_dir, if error? */ 437 438 done: 439 mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); 440 affs_brelse(bh); 441 return retval; 442 } 443