at v3.18 1235 lines 31 kB view raw
1/* 2 * dir.c 3 * 4 * Copyright (C) 1995, 1996 by Volker Lendecke 5 * Modified for big endian by J.F. Chadima and David S. Miller 6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 7 * Modified 1998, 1999 Wolfram Pienkoss for NLS 8 * Modified 1999 Wolfram Pienkoss for directory caching 9 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info 10 * 11 */ 12 13 14#include <linux/time.h> 15#include <linux/errno.h> 16#include <linux/stat.h> 17#include <linux/kernel.h> 18#include <linux/vmalloc.h> 19#include <linux/mm.h> 20#include <linux/namei.h> 21#include <asm/uaccess.h> 22#include <asm/byteorder.h> 23 24#include "ncp_fs.h" 25 26static void ncp_read_volume_list(struct file *, struct dir_context *, 27 struct ncp_cache_control *); 28static void ncp_do_readdir(struct file *, struct dir_context *, 29 struct ncp_cache_control *); 30 31static int ncp_readdir(struct file *, struct dir_context *); 32 33static int ncp_create(struct inode *, struct dentry *, umode_t, bool); 34static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); 35static int ncp_unlink(struct inode *, struct dentry *); 36static int ncp_mkdir(struct inode *, struct dentry *, umode_t); 37static int ncp_rmdir(struct inode *, struct dentry *); 38static int ncp_rename(struct inode *, struct dentry *, 39 struct inode *, struct dentry *); 40static int ncp_mknod(struct inode * dir, struct dentry *dentry, 41 umode_t mode, dev_t rdev); 42#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 43extern int ncp_symlink(struct inode *, struct dentry *, const char *); 44#else 45#define ncp_symlink NULL 46#endif 47 48const struct file_operations ncp_dir_operations = 49{ 50 .llseek = generic_file_llseek, 51 .read = generic_read_dir, 52 .iterate = ncp_readdir, 53 .unlocked_ioctl = ncp_ioctl, 54#ifdef CONFIG_COMPAT 55 .compat_ioctl = ncp_compat_ioctl, 56#endif 57}; 58 59const struct inode_operations ncp_dir_inode_operations = 60{ 61 .create = ncp_create, 62 .lookup = ncp_lookup, 63 .unlink = ncp_unlink, 64 .symlink = ncp_symlink, 65 .mkdir = ncp_mkdir, 66 .rmdir = ncp_rmdir, 67 .mknod = ncp_mknod, 68 .rename = ncp_rename, 69 .setattr = ncp_notify_change, 70}; 71 72/* 73 * Dentry operations routines 74 */ 75static int ncp_lookup_validate(struct dentry *, unsigned int); 76static int ncp_hash_dentry(const struct dentry *, struct qstr *); 77static int ncp_compare_dentry(const struct dentry *, const struct dentry *, 78 unsigned int, const char *, const struct qstr *); 79static int ncp_delete_dentry(const struct dentry *); 80 81const struct dentry_operations ncp_dentry_operations = 82{ 83 .d_revalidate = ncp_lookup_validate, 84 .d_hash = ncp_hash_dentry, 85 .d_compare = ncp_compare_dentry, 86 .d_delete = ncp_delete_dentry, 87}; 88 89#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) 90 91static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) 92{ 93#ifdef CONFIG_NCPFS_SMALLDOS 94 int ns = ncp_namespace(i); 95 96 if ((ns == NW_NS_DOS) 97#ifdef CONFIG_NCPFS_OS2_NS 98 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) 99#endif /* CONFIG_NCPFS_OS2_NS */ 100 ) 101 return 0; 102#endif /* CONFIG_NCPFS_SMALLDOS */ 103 return 1; 104} 105 106#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) 107 108static inline int ncp_case_sensitive(const struct inode *i) 109{ 110#ifdef CONFIG_NCPFS_NFS_NS 111 return ncp_namespace(i) == NW_NS_NFS; 112#else 113 return 0; 114#endif /* CONFIG_NCPFS_NFS_NS */ 115} 116 117/* 118 * Note: leave the hash unchanged if the directory 119 * is case-sensitive. 120 * 121 * Accessing the parent inode can be racy under RCU pathwalking. 122 * Use ACCESS_ONCE() to make sure we use _one_ particular inode, 123 * the callers will handle races. 124 */ 125static int 126ncp_hash_dentry(const struct dentry *dentry, struct qstr *this) 127{ 128 struct inode *inode = ACCESS_ONCE(dentry->d_inode); 129 130 if (!inode) 131 return 0; 132 133 if (!ncp_case_sensitive(inode)) { 134 struct super_block *sb = dentry->d_sb; 135 struct nls_table *t; 136 unsigned long hash; 137 int i; 138 139 t = NCP_IO_TABLE(sb); 140 hash = init_name_hash(); 141 for (i=0; i<this->len ; i++) 142 hash = partial_name_hash(ncp_tolower(t, this->name[i]), 143 hash); 144 this->hash = end_name_hash(hash); 145 } 146 return 0; 147} 148 149/* 150 * Accessing the parent inode can be racy under RCU pathwalking. 151 * Use ACCESS_ONCE() to make sure we use _one_ particular inode, 152 * the callers will handle races. 153 */ 154static int 155ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry, 156 unsigned int len, const char *str, const struct qstr *name) 157{ 158 struct inode *pinode; 159 160 if (len != name->len) 161 return 1; 162 163 pinode = ACCESS_ONCE(parent->d_inode); 164 if (!pinode) 165 return 1; 166 167 if (ncp_case_sensitive(pinode)) 168 return strncmp(str, name->name, len); 169 170 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len); 171} 172 173/* 174 * This is the callback from dput() when d_count is going to 0. 175 * We use this to unhash dentries with bad inodes. 176 * Closing files can be safely postponed until iput() - it's done there anyway. 177 */ 178static int 179ncp_delete_dentry(const struct dentry * dentry) 180{ 181 struct inode *inode = dentry->d_inode; 182 183 if (inode) { 184 if (is_bad_inode(inode)) 185 return 1; 186 } else 187 { 188 /* N.B. Unhash negative dentries? */ 189 } 190 return 0; 191} 192 193static inline int 194ncp_single_volume(struct ncp_server *server) 195{ 196 return (server->m.mounted_vol[0] != '\0'); 197} 198 199static inline int ncp_is_server_root(struct inode *inode) 200{ 201 return (!ncp_single_volume(NCP_SERVER(inode)) && 202 inode == inode->i_sb->s_root->d_inode); 203} 204 205 206/* 207 * This is the callback when the dcache has a lookup hit. 208 */ 209 210 211#ifdef CONFIG_NCPFS_STRONG 212/* try to delete a readonly file (NW R bit set) */ 213 214static int 215ncp_force_unlink(struct inode *dir, struct dentry* dentry) 216{ 217 int res=0x9c,res2; 218 struct nw_modify_dos_info info; 219 __le32 old_nwattr; 220 struct inode *inode; 221 222 memset(&info, 0, sizeof(info)); 223 224 /* remove the Read-Only flag on the NW server */ 225 inode = dentry->d_inode; 226 227 old_nwattr = NCP_FINFO(inode)->nwattr; 228 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); 229 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); 230 if (res2) 231 goto leave_me; 232 233 /* now try again the delete operation */ 234 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); 235 236 if (res) /* delete failed, set R bit again */ 237 { 238 info.attributes = old_nwattr; 239 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); 240 if (res2) 241 goto leave_me; 242 } 243leave_me: 244 return(res); 245} 246#endif /* CONFIG_NCPFS_STRONG */ 247 248#ifdef CONFIG_NCPFS_STRONG 249static int 250ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, 251 struct inode *new_dir, struct dentry* new_dentry, char *_new_name) 252{ 253 struct nw_modify_dos_info info; 254 int res=0x90,res2; 255 struct inode *old_inode = old_dentry->d_inode; 256 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr; 257 __le32 new_nwattr = 0; /* shut compiler warning */ 258 int old_nwattr_changed = 0; 259 int new_nwattr_changed = 0; 260 261 memset(&info, 0, sizeof(info)); 262 263 /* remove the Read-Only flag on the NW server */ 264 265 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 266 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); 267 if (!res2) 268 old_nwattr_changed = 1; 269 if (new_dentry && new_dentry->d_inode) { 270 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr; 271 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 272 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); 273 if (!res2) 274 new_nwattr_changed = 1; 275 } 276 /* now try again the rename operation */ 277 /* but only if something really happened */ 278 if (new_nwattr_changed || old_nwattr_changed) { 279 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), 280 old_dir, _old_name, 281 new_dir, _new_name); 282 } 283 if (res) 284 goto leave_me; 285 /* file was successfully renamed, so: 286 do not set attributes on old file - it no longer exists 287 copy attributes from old file to new */ 288 new_nwattr_changed = old_nwattr_changed; 289 new_nwattr = old_nwattr; 290 old_nwattr_changed = 0; 291 292leave_me:; 293 if (old_nwattr_changed) { 294 info.attributes = old_nwattr; 295 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); 296 /* ignore errors */ 297 } 298 if (new_nwattr_changed) { 299 info.attributes = new_nwattr; 300 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); 301 /* ignore errors */ 302 } 303 return(res); 304} 305#endif /* CONFIG_NCPFS_STRONG */ 306 307 308static int 309ncp_lookup_validate(struct dentry *dentry, unsigned int flags) 310{ 311 struct ncp_server *server; 312 struct dentry *parent; 313 struct inode *dir; 314 struct ncp_entry_info finfo; 315 int res, val = 0, len; 316 __u8 __name[NCP_MAXPATHLEN + 1]; 317 318 if (dentry == dentry->d_sb->s_root) 319 return 1; 320 321 if (flags & LOOKUP_RCU) 322 return -ECHILD; 323 324 parent = dget_parent(dentry); 325 dir = parent->d_inode; 326 327 if (!dentry->d_inode) 328 goto finished; 329 330 server = NCP_SERVER(dir); 331 332 /* 333 * Inspired by smbfs: 334 * The default validation is based on dentry age: 335 * We set the max age at mount time. (But each 336 * successful server lookup renews the timestamp.) 337 */ 338 val = NCP_TEST_AGE(server, dentry); 339 if (val) 340 goto finished; 341 342 ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n", 343 dentry, NCP_GET_AGE(dentry)); 344 345 len = sizeof(__name); 346 if (ncp_is_server_root(dir)) { 347 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 348 dentry->d_name.len, 1); 349 if (!res) { 350 res = ncp_lookup_volume(server, __name, &(finfo.i)); 351 if (!res) 352 ncp_update_known_namespace(server, finfo.i.volNumber, NULL); 353 } 354 } else { 355 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 356 dentry->d_name.len, !ncp_preserve_case(dir)); 357 if (!res) 358 res = ncp_obtain_info(server, dir, __name, &(finfo.i)); 359 } 360 finfo.volume = finfo.i.volNumber; 361 ncp_dbg(2, "looked for %pd/%s, res=%d\n", 362 dentry->d_parent, __name, res); 363 /* 364 * If we didn't find it, or if it has a different dirEntNum to 365 * what we remember, it's not valid any more. 366 */ 367 if (!res) { 368 struct inode *inode = dentry->d_inode; 369 370 mutex_lock(&inode->i_mutex); 371 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { 372 ncp_new_dentry(dentry); 373 val=1; 374 } else 375 ncp_dbg(2, "found, but dirEntNum changed\n"); 376 377 ncp_update_inode2(inode, &finfo); 378 mutex_unlock(&inode->i_mutex); 379 } 380 381finished: 382 ncp_dbg(2, "result=%d\n", val); 383 dput(parent); 384 return val; 385} 386 387static struct dentry * 388ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) 389{ 390 struct dentry *dent = dentry; 391 392 if (d_validate(dent, parent)) { 393 if (dent->d_name.len <= NCP_MAXPATHLEN && 394 (unsigned long)dent->d_fsdata == fpos) { 395 if (!dent->d_inode) { 396 dput(dent); 397 dent = NULL; 398 } 399 return dent; 400 } 401 dput(dent); 402 } 403 404 /* If a pointer is invalid, we search the dentry. */ 405 spin_lock(&parent->d_lock); 406 list_for_each_entry(dent, &parent->d_subdirs, d_u.d_child) { 407 if ((unsigned long)dent->d_fsdata == fpos) { 408 if (dent->d_inode) 409 dget(dent); 410 else 411 dent = NULL; 412 spin_unlock(&parent->d_lock); 413 goto out; 414 } 415 } 416 spin_unlock(&parent->d_lock); 417 return NULL; 418 419out: 420 return dent; 421} 422 423static time_t ncp_obtain_mtime(struct dentry *dentry) 424{ 425 struct inode *inode = dentry->d_inode; 426 struct ncp_server *server = NCP_SERVER(inode); 427 struct nw_info_struct i; 428 429 if (!ncp_conn_valid(server) || ncp_is_server_root(inode)) 430 return 0; 431 432 if (ncp_obtain_info(server, inode, NULL, &i)) 433 return 0; 434 435 return ncp_date_dos2unix(i.modifyTime, i.modifyDate); 436} 437 438static int ncp_readdir(struct file *file, struct dir_context *ctx) 439{ 440 struct dentry *dentry = file->f_path.dentry; 441 struct inode *inode = dentry->d_inode; 442 struct page *page = NULL; 443 struct ncp_server *server = NCP_SERVER(inode); 444 union ncp_dir_cache *cache = NULL; 445 struct ncp_cache_control ctl; 446 int result, mtime_valid = 0; 447 time_t mtime = 0; 448 449 ctl.page = NULL; 450 ctl.cache = NULL; 451 452 ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos); 453 454 result = -EIO; 455 /* Do not generate '.' and '..' when server is dead. */ 456 if (!ncp_conn_valid(server)) 457 goto out; 458 459 result = 0; 460 if (!dir_emit_dots(file, ctx)) 461 goto out; 462 463 page = grab_cache_page(&inode->i_data, 0); 464 if (!page) 465 goto read_really; 466 467 ctl.cache = cache = kmap(page); 468 ctl.head = cache->head; 469 470 if (!PageUptodate(page) || !ctl.head.eof) 471 goto init_cache; 472 473 if (ctx->pos == 2) { 474 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) 475 goto init_cache; 476 477 mtime = ncp_obtain_mtime(dentry); 478 mtime_valid = 1; 479 if ((!mtime) || (mtime != ctl.head.mtime)) 480 goto init_cache; 481 } 482 483 if (ctx->pos > ctl.head.end) 484 goto finished; 485 486 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2); 487 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; 488 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; 489 490 for (;;) { 491 if (ctl.ofs != 0) { 492 ctl.page = find_lock_page(&inode->i_data, ctl.ofs); 493 if (!ctl.page) 494 goto invalid_cache; 495 ctl.cache = kmap(ctl.page); 496 if (!PageUptodate(ctl.page)) 497 goto invalid_cache; 498 } 499 while (ctl.idx < NCP_DIRCACHE_SIZE) { 500 struct dentry *dent; 501 bool over; 502 503 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], 504 dentry, ctx->pos); 505 if (!dent) 506 goto invalid_cache; 507 over = !dir_emit(ctx, dent->d_name.name, 508 dent->d_name.len, 509 dent->d_inode->i_ino, DT_UNKNOWN); 510 dput(dent); 511 if (over) 512 goto finished; 513 ctx->pos += 1; 514 ctl.idx += 1; 515 if (ctx->pos > ctl.head.end) 516 goto finished; 517 } 518 if (ctl.page) { 519 kunmap(ctl.page); 520 SetPageUptodate(ctl.page); 521 unlock_page(ctl.page); 522 page_cache_release(ctl.page); 523 ctl.page = NULL; 524 } 525 ctl.idx = 0; 526 ctl.ofs += 1; 527 } 528invalid_cache: 529 if (ctl.page) { 530 kunmap(ctl.page); 531 unlock_page(ctl.page); 532 page_cache_release(ctl.page); 533 ctl.page = NULL; 534 } 535 ctl.cache = cache; 536init_cache: 537 ncp_invalidate_dircache_entries(dentry); 538 if (!mtime_valid) { 539 mtime = ncp_obtain_mtime(dentry); 540 mtime_valid = 1; 541 } 542 ctl.head.mtime = mtime; 543 ctl.head.time = jiffies; 544 ctl.head.eof = 0; 545 ctl.fpos = 2; 546 ctl.ofs = 0; 547 ctl.idx = NCP_DIRCACHE_START; 548 ctl.filled = 0; 549 ctl.valid = 1; 550read_really: 551 if (ncp_is_server_root(inode)) { 552 ncp_read_volume_list(file, ctx, &ctl); 553 } else { 554 ncp_do_readdir(file, ctx, &ctl); 555 } 556 ctl.head.end = ctl.fpos - 1; 557 ctl.head.eof = ctl.valid; 558finished: 559 if (ctl.page) { 560 kunmap(ctl.page); 561 SetPageUptodate(ctl.page); 562 unlock_page(ctl.page); 563 page_cache_release(ctl.page); 564 } 565 if (page) { 566 cache->head = ctl.head; 567 kunmap(page); 568 SetPageUptodate(page); 569 unlock_page(page); 570 page_cache_release(page); 571 } 572out: 573 return result; 574} 575 576static int 577ncp_fill_cache(struct file *file, struct dir_context *ctx, 578 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, 579 int inval_childs) 580{ 581 struct dentry *newdent, *dentry = file->f_path.dentry; 582 struct inode *dir = dentry->d_inode; 583 struct ncp_cache_control ctl = *ctrl; 584 struct qstr qname; 585 int valid = 0; 586 int hashed = 0; 587 ino_t ino = 0; 588 __u8 __name[NCP_MAXPATHLEN + 1]; 589 590 qname.len = sizeof(__name); 591 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, 592 entry->i.entryName, entry->i.nameLen, 593 !ncp_preserve_entry_case(dir, entry->i.NSCreator))) 594 return 1; /* I'm not sure */ 595 596 qname.name = __name; 597 598 newdent = d_hash_and_lookup(dentry, &qname); 599 if (unlikely(IS_ERR(newdent))) 600 goto end_advance; 601 if (!newdent) { 602 newdent = d_alloc(dentry, &qname); 603 if (!newdent) 604 goto end_advance; 605 } else { 606 hashed = 1; 607 608 /* If case sensitivity changed for this volume, all entries below this one 609 should be thrown away. This entry itself is not affected, as its case 610 sensitivity is controlled by its own parent. */ 611 if (inval_childs) 612 shrink_dcache_parent(newdent); 613 614 /* 615 * NetWare's OS2 namespace is case preserving yet case 616 * insensitive. So we update dentry's name as received from 617 * server. Parent dir's i_mutex is locked because we're in 618 * readdir. 619 */ 620 dentry_update_name_case(newdent, &qname); 621 } 622 623 if (!newdent->d_inode) { 624 struct inode *inode; 625 626 entry->opened = 0; 627 entry->ino = iunique(dir->i_sb, 2); 628 inode = ncp_iget(dir->i_sb, entry); 629 if (inode) { 630 d_instantiate(newdent, inode); 631 if (!hashed) 632 d_rehash(newdent); 633 } 634 } else { 635 struct inode *inode = newdent->d_inode; 636 637 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); 638 ncp_update_inode2(inode, entry); 639 mutex_unlock(&inode->i_mutex); 640 } 641 642 if (newdent->d_inode) { 643 ino = newdent->d_inode->i_ino; 644 newdent->d_fsdata = (void *) ctl.fpos; 645 ncp_new_dentry(newdent); 646 } 647 648 if (ctl.idx >= NCP_DIRCACHE_SIZE) { 649 if (ctl.page) { 650 kunmap(ctl.page); 651 SetPageUptodate(ctl.page); 652 unlock_page(ctl.page); 653 page_cache_release(ctl.page); 654 } 655 ctl.cache = NULL; 656 ctl.idx -= NCP_DIRCACHE_SIZE; 657 ctl.ofs += 1; 658 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); 659 if (ctl.page) 660 ctl.cache = kmap(ctl.page); 661 } 662 if (ctl.cache) { 663 ctl.cache->dentry[ctl.idx] = newdent; 664 valid = 1; 665 } 666 dput(newdent); 667end_advance: 668 if (!valid) 669 ctl.valid = 0; 670 if (!ctl.filled && (ctl.fpos == ctx->pos)) { 671 if (!ino) 672 ino = iunique(dir->i_sb, 2); 673 ctl.filled = !dir_emit(ctx, qname.name, qname.len, 674 ino, DT_UNKNOWN); 675 if (!ctl.filled) 676 ctx->pos += 1; 677 } 678 ctl.fpos += 1; 679 ctl.idx += 1; 680 *ctrl = ctl; 681 return (ctl.valid || !ctl.filled); 682} 683 684static void 685ncp_read_volume_list(struct file *file, struct dir_context *ctx, 686 struct ncp_cache_control *ctl) 687{ 688 struct dentry *dentry = file->f_path.dentry; 689 struct inode *inode = dentry->d_inode; 690 struct ncp_server *server = NCP_SERVER(inode); 691 struct ncp_volume_info info; 692 struct ncp_entry_info entry; 693 int i; 694 695 ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos); 696 697 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { 698 int inval_dentry; 699 700 if (ncp_get_volume_info_with_number(server, i, &info) != 0) 701 return; 702 if (!strlen(info.volume_name)) 703 continue; 704 705 ncp_dbg(1, "found vol: %s\n", info.volume_name); 706 707 if (ncp_lookup_volume(server, info.volume_name, 708 &entry.i)) { 709 ncp_dbg(1, "could not lookup vol %s\n", 710 info.volume_name); 711 continue; 712 } 713 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); 714 entry.volume = entry.i.volNumber; 715 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry)) 716 return; 717 } 718} 719 720static void 721ncp_do_readdir(struct file *file, struct dir_context *ctx, 722 struct ncp_cache_control *ctl) 723{ 724 struct dentry *dentry = file->f_path.dentry; 725 struct inode *dir = dentry->d_inode; 726 struct ncp_server *server = NCP_SERVER(dir); 727 struct nw_search_sequence seq; 728 struct ncp_entry_info entry; 729 int err; 730 void* buf; 731 int more; 732 size_t bufsize; 733 734 ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos); 735 ncp_vdbg("init %pD, volnum=%d, dirent=%u\n", 736 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); 737 738 err = ncp_initialize_search(server, dir, &seq); 739 if (err) { 740 ncp_dbg(1, "init failed, err=%d\n", err); 741 return; 742 } 743 /* We MUST NOT use server->buffer_size handshaked with server if we are 744 using UDP, as for UDP server uses max. buffer size determined by 745 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 746 So we use 128KB, just to be sure, as there is no way how to know 747 this value in advance. */ 748 bufsize = 131072; 749 buf = vmalloc(bufsize); 750 if (!buf) 751 return; 752 do { 753 int cnt; 754 char* rpl; 755 size_t rpls; 756 757 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); 758 if (err) /* Error */ 759 break; 760 if (!cnt) /* prevent endless loop */ 761 break; 762 while (cnt--) { 763 size_t onerpl; 764 765 if (rpls < offsetof(struct nw_info_struct, entryName)) 766 break; /* short packet */ 767 ncp_extract_file_info(rpl, &entry.i); 768 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; 769 if (rpls < onerpl) 770 break; /* short packet */ 771 (void)ncp_obtain_nfs_info(server, &entry.i); 772 rpl += onerpl; 773 rpls -= onerpl; 774 entry.volume = entry.i.volNumber; 775 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0)) 776 break; 777 } 778 } while (more); 779 vfree(buf); 780 return; 781} 782 783int ncp_conn_logged_in(struct super_block *sb) 784{ 785 struct ncp_server* server = NCP_SBP(sb); 786 int result; 787 788 if (ncp_single_volume(server)) { 789 int len; 790 struct dentry* dent; 791 __u32 volNumber; 792 __le32 dirEntNum; 793 __le32 DosDirNum; 794 __u8 __name[NCP_MAXPATHLEN + 1]; 795 796 len = sizeof(__name); 797 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, 798 strlen(server->m.mounted_vol), 1); 799 if (result) 800 goto out; 801 result = -ENOENT; 802 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { 803 ncp_vdbg("%s not found\n", server->m.mounted_vol); 804 goto out; 805 } 806 dent = sb->s_root; 807 if (dent) { 808 struct inode* ino = dent->d_inode; 809 if (ino) { 810 ncp_update_known_namespace(server, volNumber, NULL); 811 NCP_FINFO(ino)->volNumber = volNumber; 812 NCP_FINFO(ino)->dirEntNum = dirEntNum; 813 NCP_FINFO(ino)->DosDirNum = DosDirNum; 814 result = 0; 815 } else { 816 ncp_dbg(1, "sb->s_root->d_inode == NULL!\n"); 817 } 818 } else { 819 ncp_dbg(1, "sb->s_root == NULL!\n"); 820 } 821 } else 822 result = 0; 823 824out: 825 return result; 826} 827 828static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 829{ 830 struct ncp_server *server = NCP_SERVER(dir); 831 struct inode *inode = NULL; 832 struct ncp_entry_info finfo; 833 int error, res, len; 834 __u8 __name[NCP_MAXPATHLEN + 1]; 835 836 error = -EIO; 837 if (!ncp_conn_valid(server)) 838 goto finished; 839 840 ncp_vdbg("server lookup for %pd2\n", dentry); 841 842 len = sizeof(__name); 843 if (ncp_is_server_root(dir)) { 844 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 845 dentry->d_name.len, 1); 846 if (!res) 847 res = ncp_lookup_volume(server, __name, &(finfo.i)); 848 if (!res) 849 ncp_update_known_namespace(server, finfo.i.volNumber, NULL); 850 } else { 851 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 852 dentry->d_name.len, !ncp_preserve_case(dir)); 853 if (!res) 854 res = ncp_obtain_info(server, dir, __name, &(finfo.i)); 855 } 856 ncp_vdbg("looked for %pd2, res=%d\n", dentry, res); 857 /* 858 * If we didn't find an entry, make a negative dentry. 859 */ 860 if (res) 861 goto add_entry; 862 863 /* 864 * Create an inode for the entry. 865 */ 866 finfo.opened = 0; 867 finfo.ino = iunique(dir->i_sb, 2); 868 finfo.volume = finfo.i.volNumber; 869 error = -EACCES; 870 inode = ncp_iget(dir->i_sb, &finfo); 871 872 if (inode) { 873 ncp_new_dentry(dentry); 874add_entry: 875 d_add(dentry, inode); 876 error = 0; 877 } 878 879finished: 880 ncp_vdbg("result=%d\n", error); 881 return ERR_PTR(error); 882} 883 884/* 885 * This code is common to create, mkdir, and mknod. 886 */ 887static int ncp_instantiate(struct inode *dir, struct dentry *dentry, 888 struct ncp_entry_info *finfo) 889{ 890 struct inode *inode; 891 int error = -EINVAL; 892 893 finfo->ino = iunique(dir->i_sb, 2); 894 inode = ncp_iget(dir->i_sb, finfo); 895 if (!inode) 896 goto out_close; 897 d_instantiate(dentry,inode); 898 error = 0; 899out: 900 return error; 901 902out_close: 903 ncp_vdbg("%pd2 failed, closing file\n", dentry); 904 ncp_close_file(NCP_SERVER(dir), finfo->file_handle); 905 goto out; 906} 907 908int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, 909 dev_t rdev, __le32 attributes) 910{ 911 struct ncp_server *server = NCP_SERVER(dir); 912 struct ncp_entry_info finfo; 913 int error, result, len; 914 int opmode; 915 __u8 __name[NCP_MAXPATHLEN + 1]; 916 917 ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode); 918 919 ncp_age_dentry(server, dentry); 920 len = sizeof(__name); 921 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 922 dentry->d_name.len, !ncp_preserve_case(dir)); 923 if (error) 924 goto out; 925 926 error = -EACCES; 927 928 if (S_ISREG(mode) && 929 (server->m.flags & NCP_MOUNT_EXTRAS) && 930 (mode & S_IXUGO)) 931 attributes |= aSYSTEM | aSHARED; 932 933 result = ncp_open_create_file_or_subdir(server, dir, __name, 934 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, 935 attributes, AR_READ | AR_WRITE, &finfo); 936 opmode = O_RDWR; 937 if (result) { 938 result = ncp_open_create_file_or_subdir(server, dir, __name, 939 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, 940 attributes, AR_WRITE, &finfo); 941 if (result) { 942 if (result == 0x87) 943 error = -ENAMETOOLONG; 944 else if (result < 0) 945 error = result; 946 ncp_dbg(1, "%pd2 failed\n", dentry); 947 goto out; 948 } 949 opmode = O_WRONLY; 950 } 951 finfo.access = opmode; 952 if (ncp_is_nfs_extras(server, finfo.volume)) { 953 finfo.i.nfs.mode = mode; 954 finfo.i.nfs.rdev = new_encode_dev(rdev); 955 if (ncp_modify_nfs_info(server, finfo.volume, 956 finfo.i.dirEntNum, 957 mode, new_encode_dev(rdev)) != 0) 958 goto out; 959 } 960 961 error = ncp_instantiate(dir, dentry, &finfo); 962out: 963 return error; 964} 965 966static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, 967 bool excl) 968{ 969 return ncp_create_new(dir, dentry, mode, 0, 0); 970} 971 972static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 973{ 974 struct ncp_entry_info finfo; 975 struct ncp_server *server = NCP_SERVER(dir); 976 int error, len; 977 __u8 __name[NCP_MAXPATHLEN + 1]; 978 979 ncp_dbg(1, "making %pd2\n", dentry); 980 981 ncp_age_dentry(server, dentry); 982 len = sizeof(__name); 983 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 984 dentry->d_name.len, !ncp_preserve_case(dir)); 985 if (error) 986 goto out; 987 988 error = ncp_open_create_file_or_subdir(server, dir, __name, 989 OC_MODE_CREATE, aDIR, 990 cpu_to_le16(0xffff), 991 &finfo); 992 if (error == 0) { 993 if (ncp_is_nfs_extras(server, finfo.volume)) { 994 mode |= S_IFDIR; 995 finfo.i.nfs.mode = mode; 996 if (ncp_modify_nfs_info(server, 997 finfo.volume, 998 finfo.i.dirEntNum, 999 mode, 0) != 0) 1000 goto out; 1001 } 1002 error = ncp_instantiate(dir, dentry, &finfo); 1003 } else if (error > 0) { 1004 error = -EACCES; 1005 } 1006out: 1007 return error; 1008} 1009 1010static int ncp_rmdir(struct inode *dir, struct dentry *dentry) 1011{ 1012 struct ncp_server *server = NCP_SERVER(dir); 1013 int error, result, len; 1014 __u8 __name[NCP_MAXPATHLEN + 1]; 1015 1016 ncp_dbg(1, "removing %pd2\n", dentry); 1017 1018 len = sizeof(__name); 1019 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 1020 dentry->d_name.len, !ncp_preserve_case(dir)); 1021 if (error) 1022 goto out; 1023 1024 result = ncp_del_file_or_subdir(server, dir, __name); 1025 switch (result) { 1026 case 0x00: 1027 error = 0; 1028 break; 1029 case 0x85: /* unauthorized to delete file */ 1030 case 0x8A: /* unauthorized to delete file */ 1031 error = -EACCES; 1032 break; 1033 case 0x8F: 1034 case 0x90: /* read only */ 1035 error = -EPERM; 1036 break; 1037 case 0x9F: /* in use by another client */ 1038 error = -EBUSY; 1039 break; 1040 case 0xA0: /* directory not empty */ 1041 error = -ENOTEMPTY; 1042 break; 1043 case 0xFF: /* someone deleted file */ 1044 error = -ENOENT; 1045 break; 1046 default: 1047 error = result < 0 ? result : -EACCES; 1048 break; 1049 } 1050out: 1051 return error; 1052} 1053 1054static int ncp_unlink(struct inode *dir, struct dentry *dentry) 1055{ 1056 struct inode *inode = dentry->d_inode; 1057 struct ncp_server *server; 1058 int error; 1059 1060 server = NCP_SERVER(dir); 1061 ncp_dbg(1, "unlinking %pd2\n", dentry); 1062 1063 /* 1064 * Check whether to close the file ... 1065 */ 1066 if (inode) { 1067 ncp_vdbg("closing file\n"); 1068 ncp_make_closed(inode); 1069 } 1070 1071 error = ncp_del_file_or_subdir2(server, dentry); 1072#ifdef CONFIG_NCPFS_STRONG 1073 /* 9C is Invalid path.. It should be 8F, 90 - read only, but 1074 it is not :-( */ 1075 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ 1076 error = ncp_force_unlink(dir, dentry); 1077 } 1078#endif 1079 switch (error) { 1080 case 0x00: 1081 ncp_dbg(1, "removed %pd2\n", dentry); 1082 break; 1083 case 0x85: 1084 case 0x8A: 1085 error = -EACCES; 1086 break; 1087 case 0x8D: /* some files in use */ 1088 case 0x8E: /* all files in use */ 1089 error = -EBUSY; 1090 break; 1091 case 0x8F: /* some read only */ 1092 case 0x90: /* all read only */ 1093 case 0x9C: /* !!! returned when in-use or read-only by NW4 */ 1094 error = -EPERM; 1095 break; 1096 case 0xFF: 1097 error = -ENOENT; 1098 break; 1099 default: 1100 error = error < 0 ? error : -EACCES; 1101 break; 1102 } 1103 return error; 1104} 1105 1106static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, 1107 struct inode *new_dir, struct dentry *new_dentry) 1108{ 1109 struct ncp_server *server = NCP_SERVER(old_dir); 1110 int error; 1111 int old_len, new_len; 1112 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; 1113 1114 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry); 1115 1116 ncp_age_dentry(server, old_dentry); 1117 ncp_age_dentry(server, new_dentry); 1118 1119 old_len = sizeof(__old_name); 1120 error = ncp_io2vol(server, __old_name, &old_len, 1121 old_dentry->d_name.name, old_dentry->d_name.len, 1122 !ncp_preserve_case(old_dir)); 1123 if (error) 1124 goto out; 1125 1126 new_len = sizeof(__new_name); 1127 error = ncp_io2vol(server, __new_name, &new_len, 1128 new_dentry->d_name.name, new_dentry->d_name.len, 1129 !ncp_preserve_case(new_dir)); 1130 if (error) 1131 goto out; 1132 1133 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, 1134 new_dir, __new_name); 1135#ifdef CONFIG_NCPFS_STRONG 1136 if ((error == 0x90 || error == 0x8B || error == -EACCES) && 1137 server->m.flags & NCP_MOUNT_STRONG) { /* RO */ 1138 error = ncp_force_rename(old_dir, old_dentry, __old_name, 1139 new_dir, new_dentry, __new_name); 1140 } 1141#endif 1142 switch (error) { 1143 case 0x00: 1144 ncp_dbg(1, "renamed %pd -> %pd\n", 1145 old_dentry, new_dentry); 1146 break; 1147 case 0x9E: 1148 error = -ENAMETOOLONG; 1149 break; 1150 case 0xFF: 1151 error = -ENOENT; 1152 break; 1153 default: 1154 error = error < 0 ? error : -EACCES; 1155 break; 1156 } 1157out: 1158 return error; 1159} 1160 1161static int ncp_mknod(struct inode * dir, struct dentry *dentry, 1162 umode_t mode, dev_t rdev) 1163{ 1164 if (!new_valid_dev(rdev)) 1165 return -EINVAL; 1166 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { 1167 ncp_dbg(1, "mode = 0%ho\n", mode); 1168 return ncp_create_new(dir, dentry, mode, rdev, 0); 1169 } 1170 return -EPERM; /* Strange, but true */ 1171} 1172 1173/* The following routines are taken directly from msdos-fs */ 1174 1175/* Linear day numbers of the respective 1sts in non-leap years. */ 1176 1177static int day_n[] = 1178{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; 1179/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ 1180 1181static int utc2local(int time) 1182{ 1183 return time - sys_tz.tz_minuteswest * 60; 1184} 1185 1186static int local2utc(int time) 1187{ 1188 return time + sys_tz.tz_minuteswest * 60; 1189} 1190 1191/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ 1192int 1193ncp_date_dos2unix(__le16 t, __le16 d) 1194{ 1195 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d); 1196 int month, year, secs; 1197 1198 /* first subtract and mask after that... Otherwise, if 1199 date == 0, bad things happen */ 1200 month = ((date >> 5) - 1) & 15; 1201 year = date >> 9; 1202 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 1203 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 1204 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); 1205 /* days since 1.1.70 plus 80's leap day */ 1206 return local2utc(secs); 1207} 1208 1209 1210/* Convert linear UNIX date to a MS-DOS time/date pair. */ 1211void 1212ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date) 1213{ 1214 int day, year, nl_day, month; 1215 1216 unix_date = utc2local(unix_date); 1217 *time = cpu_to_le16( 1218 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + 1219 (((unix_date / 3600) % 24) << 11)); 1220 day = unix_date / 86400 - 3652; 1221 year = day / 365; 1222 if ((year + 3) / 4 + 365 * year > day) 1223 year--; 1224 day -= (year + 3) / 4 + 365 * year; 1225 if (day == 59 && !(year & 3)) { 1226 nl_day = day; 1227 month = 2; 1228 } else { 1229 nl_day = (year & 3) || day <= 59 ? day : day - 1; 1230 for (month = 1; month < 12; month++) 1231 if (day_n[month] > nl_day) 1232 break; 1233 } 1234 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); 1235}