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