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