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("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name); 194 195 bh = affs_bread(sb, dir->i_ino); 196 if (!bh) 197 return ERR_PTR(-EIO); 198 199 key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]); 200 201 for (;;) { 202 affs_brelse(bh); 203 if (key == 0) 204 return NULL; 205 bh = affs_bread(sb, key); 206 if (!bh) 207 return ERR_PTR(-EIO); 208 if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper)) 209 return bh; 210 key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); 211 } 212 } 213 214 struct dentry * 215 affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 216 { 217 struct super_block *sb = dir->i_sb; 218 struct buffer_head *bh; 219 struct inode *inode = NULL; 220 221 pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name); 222 223 affs_lock_dir(dir); 224 bh = affs_find_entry(dir, dentry); 225 affs_unlock_dir(dir); 226 if (IS_ERR(bh)) 227 return ERR_CAST(bh); 228 if (bh) { 229 u32 ino = bh->b_blocknr; 230 231 /* store the real header ino in d_fsdata for faster lookups */ 232 dentry->d_fsdata = (void *)(long)ino; 233 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 234 //link to dirs disabled 235 //case ST_LINKDIR: 236 case ST_LINKFILE: 237 ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original); 238 } 239 affs_brelse(bh); 240 inode = affs_iget(sb, ino); 241 if (IS_ERR(inode)) 242 return ERR_CAST(inode); 243 } 244 d_add(dentry, inode); 245 return NULL; 246 } 247 248 int 249 affs_unlink(struct inode *dir, struct dentry *dentry) 250 { 251 pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino, 252 dentry->d_inode->i_ino, 253 (int)dentry->d_name.len, dentry->d_name.name); 254 255 return affs_remove_header(dentry); 256 } 257 258 int 259 affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) 260 { 261 struct super_block *sb = dir->i_sb; 262 struct inode *inode; 263 int error; 264 265 pr_debug("AFFS: create(%lu,\"%.*s\",0%ho)\n",dir->i_ino,(int)dentry->d_name.len, 266 dentry->d_name.name,mode); 267 268 inode = affs_new_inode(dir); 269 if (!inode) 270 return -ENOSPC; 271 272 inode->i_mode = mode; 273 mode_to_prot(inode); 274 mark_inode_dirty(inode); 275 276 inode->i_op = &affs_file_inode_operations; 277 inode->i_fop = &affs_file_operations; 278 inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; 279 error = affs_add_entry(dir, inode, dentry, ST_FILE); 280 if (error) { 281 clear_nlink(inode); 282 iput(inode); 283 return error; 284 } 285 return 0; 286 } 287 288 int 289 affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 290 { 291 struct inode *inode; 292 int error; 293 294 pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%ho)\n",dir->i_ino, 295 (int)dentry->d_name.len,dentry->d_name.name,mode); 296 297 inode = affs_new_inode(dir); 298 if (!inode) 299 return -ENOSPC; 300 301 inode->i_mode = S_IFDIR | mode; 302 mode_to_prot(inode); 303 304 inode->i_op = &affs_dir_inode_operations; 305 inode->i_fop = &affs_dir_operations; 306 307 error = affs_add_entry(dir, inode, dentry, ST_USERDIR); 308 if (error) { 309 clear_nlink(inode); 310 mark_inode_dirty(inode); 311 iput(inode); 312 return error; 313 } 314 return 0; 315 } 316 317 int 318 affs_rmdir(struct inode *dir, struct dentry *dentry) 319 { 320 pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino, 321 dentry->d_inode->i_ino, 322 (int)dentry->d_name.len, dentry->d_name.name); 323 324 return affs_remove_header(dentry); 325 } 326 327 int 328 affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 329 { 330 struct super_block *sb = dir->i_sb; 331 struct buffer_head *bh; 332 struct inode *inode; 333 char *p; 334 int i, maxlen, error; 335 char c, lc; 336 337 pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino, 338 (int)dentry->d_name.len,dentry->d_name.name,symname); 339 340 maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; 341 inode = affs_new_inode(dir); 342 if (!inode) 343 return -ENOSPC; 344 345 inode->i_op = &affs_symlink_inode_operations; 346 inode->i_data.a_ops = &affs_symlink_aops; 347 inode->i_mode = S_IFLNK | 0777; 348 mode_to_prot(inode); 349 350 error = -EIO; 351 bh = affs_bread(sb, inode->i_ino); 352 if (!bh) 353 goto err; 354 i = 0; 355 p = (char *)AFFS_HEAD(bh)->table; 356 lc = '/'; 357 if (*symname == '/') { 358 struct affs_sb_info *sbi = AFFS_SB(sb); 359 while (*symname == '/') 360 symname++; 361 spin_lock(&sbi->symlink_lock); 362 while (sbi->s_volume[i]) /* Cannot overflow */ 363 *p++ = sbi->s_volume[i++]; 364 spin_unlock(&sbi->symlink_lock); 365 } 366 while (i < maxlen && (c = *symname++)) { 367 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 368 *p++ = '/'; 369 i++; 370 symname += 2; 371 lc = '/'; 372 } else if (c == '.' && lc == '/' && *symname == '/') { 373 symname++; 374 lc = '/'; 375 } else { 376 *p++ = c; 377 lc = c; 378 i++; 379 } 380 if (lc == '/') 381 while (*symname == '/') 382 symname++; 383 } 384 *p = 0; 385 mark_buffer_dirty_inode(bh, inode); 386 affs_brelse(bh); 387 mark_inode_dirty(inode); 388 389 error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); 390 if (error) 391 goto err; 392 393 return 0; 394 395 err: 396 clear_nlink(inode); 397 mark_inode_dirty(inode); 398 iput(inode); 399 return error; 400 } 401 402 int 403 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 404 { 405 struct inode *inode = old_dentry->d_inode; 406 407 pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino, 408 (int)dentry->d_name.len,dentry->d_name.name); 409 410 return affs_add_entry(dir, inode, dentry, ST_LINKFILE); 411 } 412 413 int 414 affs_rename(struct inode *old_dir, struct dentry *old_dentry, 415 struct inode *new_dir, struct dentry *new_dentry) 416 { 417 struct super_block *sb = old_dir->i_sb; 418 struct buffer_head *bh = NULL; 419 int retval; 420 421 pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", 422 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, 423 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); 424 425 retval = affs_check_name(new_dentry->d_name.name, 426 new_dentry->d_name.len, 427 affs_nofilenametruncate(old_dentry)); 428 429 if (retval) 430 return retval; 431 432 /* Unlink destination if it already exists */ 433 if (new_dentry->d_inode) { 434 retval = affs_remove_header(new_dentry); 435 if (retval) 436 return retval; 437 } 438 439 bh = affs_bread(sb, old_dentry->d_inode->i_ino); 440 if (!bh) 441 return -EIO; 442 443 /* Remove header from its parent directory. */ 444 affs_lock_dir(old_dir); 445 retval = affs_remove_hash(old_dir, bh); 446 affs_unlock_dir(old_dir); 447 if (retval) 448 goto done; 449 450 /* And insert it into the new directory with the new name. */ 451 affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); 452 affs_fix_checksum(sb, bh); 453 affs_lock_dir(new_dir); 454 retval = affs_insert_hash(new_dir, bh); 455 affs_unlock_dir(new_dir); 456 /* TODO: move it back to old_dir, if error? */ 457 458 done: 459 mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); 460 affs_brelse(bh); 461 return retval; 462 } 463