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 retval; 68 u32 len; 69 70 retval = affs_check_name(qstr->name, qstr->len, notruncate); 71 if (retval) 72 return retval; 73 74 hash = init_name_hash(); 75 len = min(qstr->len, AFFSNAMEMAX); 76 for (; len > 0; name++, len--) 77 hash = partial_name_hash(toupper(*name), hash); 78 qstr->hash = end_name_hash(hash); 79 80 return 0; 81 } 82 83 static int 84 affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 85 { 86 return __affs_hash_dentry(qstr, affs_toupper, 87 affs_nofilenametruncate(dentry)); 88 89 } 90 91 static int 92 affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 93 { 94 return __affs_hash_dentry(qstr, affs_intl_toupper, 95 affs_nofilenametruncate(dentry)); 96 97 } 98 99 static inline int __affs_compare_dentry(unsigned int len, 100 const char *str, const struct qstr *name, toupper_t toupper, 101 bool notruncate) 102 { 103 const u8 *aname = str; 104 const u8 *bname = name->name; 105 106 /* 107 * 'str' is the name of an already existing dentry, so the name 108 * must be valid. 'name' must be validated first. 109 */ 110 111 if (affs_check_name(name->name, name->len, notruncate)) 112 return 1; 113 114 /* 115 * If the names are longer than the allowed 30 chars, 116 * the excess is ignored, so their length may differ. 117 */ 118 if (len >= AFFSNAMEMAX) { 119 if (name->len < AFFSNAMEMAX) 120 return 1; 121 len = AFFSNAMEMAX; 122 } else if (len != name->len) 123 return 1; 124 125 for (; len > 0; len--) 126 if (toupper(*aname++) != toupper(*bname++)) 127 return 1; 128 129 return 0; 130 } 131 132 static int 133 affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, 134 unsigned int len, const char *str, const struct qstr *name) 135 { 136 137 return __affs_compare_dentry(len, str, name, affs_toupper, 138 affs_nofilenametruncate(parent)); 139 } 140 141 static int 142 affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, 143 unsigned int len, const char *str, const struct qstr *name) 144 { 145 return __affs_compare_dentry(len, str, name, affs_intl_toupper, 146 affs_nofilenametruncate(parent)); 147 148 } 149 150 /* 151 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure. 152 */ 153 154 static inline int 155 affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) 156 { 157 const u8 *name = dentry->d_name.name; 158 int len = dentry->d_name.len; 159 160 if (len >= AFFSNAMEMAX) { 161 if (*name2 < AFFSNAMEMAX) 162 return 0; 163 len = AFFSNAMEMAX; 164 } else if (len != *name2) 165 return 0; 166 167 for (name2++; len > 0; len--) 168 if (toupper(*name++) != toupper(*name2++)) 169 return 0; 170 return 1; 171 } 172 173 int 174 affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) 175 { 176 toupper_t toupper = affs_get_toupper(sb); 177 u32 hash; 178 179 hash = len = min(len, AFFSNAMEMAX); 180 for (; len > 0; len--) 181 hash = (hash * 13 + toupper(*name++)) & 0x7ff; 182 183 return hash % AFFS_SB(sb)->s_hashsize; 184 } 185 186 static struct buffer_head * 187 affs_find_entry(struct inode *dir, struct dentry *dentry) 188 { 189 struct super_block *sb = dir->i_sb; 190 struct buffer_head *bh; 191 toupper_t toupper = affs_get_toupper(sb); 192 u32 key; 193 194 pr_debug("%s(\"%pd\")\n", __func__, dentry); 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(\"%pd\")\n", __func__, dentry); 223 224 affs_lock_dir(dir); 225 bh = affs_find_entry(dir, dentry); 226 affs_unlock_dir(dir); 227 if (IS_ERR(bh)) 228 return ERR_CAST(bh); 229 if (bh) { 230 u32 ino = bh->b_blocknr; 231 232 /* store the real header ino in d_fsdata for faster lookups */ 233 dentry->d_fsdata = (void *)(long)ino; 234 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 235 //link to dirs disabled 236 //case ST_LINKDIR: 237 case ST_LINKFILE: 238 ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original); 239 } 240 affs_brelse(bh); 241 inode = affs_iget(sb, ino); 242 if (IS_ERR(inode)) 243 return ERR_CAST(inode); 244 } 245 d_add(dentry, inode); 246 return NULL; 247 } 248 249 int 250 affs_unlink(struct inode *dir, struct dentry *dentry) 251 { 252 pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, 253 dentry->d_inode->i_ino, dentry); 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("%s(%lu,\"%pd\",0%ho)\n", 266 __func__, dir->i_ino, dentry, 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("%s(%lu,\"%pd\",0%ho)\n", 295 __func__, dir->i_ino, dentry, 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("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, 321 dentry->d_inode->i_ino, dentry); 322 323 return affs_remove_header(dentry); 324 } 325 326 int 327 affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 328 { 329 struct super_block *sb = dir->i_sb; 330 struct buffer_head *bh; 331 struct inode *inode; 332 char *p; 333 int i, maxlen, error; 334 char c, lc; 335 336 pr_debug("%s(%lu,\"%pd\" -> \"%s\")\n", 337 __func__, dir->i_ino, dentry, symname); 338 339 maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; 340 inode = affs_new_inode(dir); 341 if (!inode) 342 return -ENOSPC; 343 344 inode->i_op = &affs_symlink_inode_operations; 345 inode->i_data.a_ops = &affs_symlink_aops; 346 inode->i_mode = S_IFLNK | 0777; 347 mode_to_prot(inode); 348 349 error = -EIO; 350 bh = affs_bread(sb, inode->i_ino); 351 if (!bh) 352 goto err; 353 i = 0; 354 p = (char *)AFFS_HEAD(bh)->table; 355 lc = '/'; 356 if (*symname == '/') { 357 struct affs_sb_info *sbi = AFFS_SB(sb); 358 while (*symname == '/') 359 symname++; 360 spin_lock(&sbi->symlink_lock); 361 while (sbi->s_volume[i]) /* Cannot overflow */ 362 *p++ = sbi->s_volume[i++]; 363 spin_unlock(&sbi->symlink_lock); 364 } 365 while (i < maxlen && (c = *symname++)) { 366 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 367 *p++ = '/'; 368 i++; 369 symname += 2; 370 lc = '/'; 371 } else if (c == '.' && lc == '/' && *symname == '/') { 372 symname++; 373 lc = '/'; 374 } else { 375 *p++ = c; 376 lc = c; 377 i++; 378 } 379 if (lc == '/') 380 while (*symname == '/') 381 symname++; 382 } 383 *p = 0; 384 mark_buffer_dirty_inode(bh, inode); 385 affs_brelse(bh); 386 mark_inode_dirty(inode); 387 388 error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); 389 if (error) 390 goto err; 391 392 return 0; 393 394 err: 395 clear_nlink(inode); 396 mark_inode_dirty(inode); 397 iput(inode); 398 return error; 399 } 400 401 int 402 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 403 { 404 struct inode *inode = old_dentry->d_inode; 405 406 pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino, 407 dentry); 408 409 return affs_add_entry(dir, inode, dentry, ST_LINKFILE); 410 } 411 412 int 413 affs_rename(struct inode *old_dir, struct dentry *old_dentry, 414 struct inode *new_dir, struct dentry *new_dentry) 415 { 416 struct super_block *sb = old_dir->i_sb; 417 struct buffer_head *bh = NULL; 418 int retval; 419 420 pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, 421 old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); 422 423 retval = affs_check_name(new_dentry->d_name.name, 424 new_dentry->d_name.len, 425 affs_nofilenametruncate(old_dentry)); 426 427 if (retval) 428 return retval; 429 430 /* Unlink destination if it already exists */ 431 if (new_dentry->d_inode) { 432 retval = affs_remove_header(new_dentry); 433 if (retval) 434 return retval; 435 } 436 437 bh = affs_bread(sb, old_dentry->d_inode->i_ino); 438 if (!bh) 439 return -EIO; 440 441 /* Remove header from its parent directory. */ 442 affs_lock_dir(old_dir); 443 retval = affs_remove_hash(old_dir, bh); 444 affs_unlock_dir(old_dir); 445 if (retval) 446 goto done; 447 448 /* And insert it into the new directory with the new name. */ 449 affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); 450 affs_fix_checksum(sb, bh); 451 affs_lock_dir(new_dir); 452 retval = affs_insert_hash(new_dir, bh); 453 affs_unlock_dir(new_dir); 454 /* TODO: move it back to old_dir, if error? */ 455 456 done: 457 mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); 458 affs_brelse(bh); 459 return retval; 460 } 461