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