inode.c revision 02b9984d640873b7b3809e63f81a0d7e13496886
1/* 2 * inode.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 Wolfram Pienkoss for NLS 8 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info 9 * 10 */ 11 12#include <linux/module.h> 13 14#include <asm/uaccess.h> 15#include <asm/byteorder.h> 16 17#include <linux/time.h> 18#include <linux/kernel.h> 19#include <linux/mm.h> 20#include <linux/string.h> 21#include <linux/stat.h> 22#include <linux/errno.h> 23#include <linux/file.h> 24#include <linux/fcntl.h> 25#include <linux/slab.h> 26#include <linux/vmalloc.h> 27#include <linux/init.h> 28#include <linux/vfs.h> 29#include <linux/mount.h> 30#include <linux/seq_file.h> 31#include <linux/namei.h> 32 33#include <net/sock.h> 34 35#include "ncp_fs.h" 36#include "getopt.h" 37 38#define NCP_DEFAULT_FILE_MODE 0600 39#define NCP_DEFAULT_DIR_MODE 0700 40#define NCP_DEFAULT_TIME_OUT 10 41#define NCP_DEFAULT_RETRY_COUNT 20 42 43static void ncp_evict_inode(struct inode *); 44static void ncp_put_super(struct super_block *); 45static int ncp_statfs(struct dentry *, struct kstatfs *); 46static int ncp_show_options(struct seq_file *, struct dentry *); 47 48static struct kmem_cache * ncp_inode_cachep; 49 50static struct inode *ncp_alloc_inode(struct super_block *sb) 51{ 52 struct ncp_inode_info *ei; 53 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); 54 if (!ei) 55 return NULL; 56 return &ei->vfs_inode; 57} 58 59static void ncp_i_callback(struct rcu_head *head) 60{ 61 struct inode *inode = container_of(head, struct inode, i_rcu); 62 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); 63} 64 65static void ncp_destroy_inode(struct inode *inode) 66{ 67 call_rcu(&inode->i_rcu, ncp_i_callback); 68} 69 70static void init_once(void *foo) 71{ 72 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; 73 74 mutex_init(&ei->open_mutex); 75 inode_init_once(&ei->vfs_inode); 76} 77 78static int init_inodecache(void) 79{ 80 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", 81 sizeof(struct ncp_inode_info), 82 0, (SLAB_RECLAIM_ACCOUNT| 83 SLAB_MEM_SPREAD), 84 init_once); 85 if (ncp_inode_cachep == NULL) 86 return -ENOMEM; 87 return 0; 88} 89 90static void destroy_inodecache(void) 91{ 92 /* 93 * Make sure all delayed rcu free inodes are flushed before we 94 * destroy cache. 95 */ 96 rcu_barrier(); 97 kmem_cache_destroy(ncp_inode_cachep); 98} 99 100static int ncp_remount(struct super_block *sb, int *flags, char* data) 101{ 102 sync_filesystem(sb); 103 *flags |= MS_NODIRATIME; 104 return 0; 105} 106 107static const struct super_operations ncp_sops = 108{ 109 .alloc_inode = ncp_alloc_inode, 110 .destroy_inode = ncp_destroy_inode, 111 .drop_inode = generic_delete_inode, 112 .evict_inode = ncp_evict_inode, 113 .put_super = ncp_put_super, 114 .statfs = ncp_statfs, 115 .remount_fs = ncp_remount, 116 .show_options = ncp_show_options, 117}; 118 119/* 120 * Fill in the ncpfs-specific information in the inode. 121 */ 122static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) 123{ 124 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; 125 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; 126 NCP_FINFO(inode)->volNumber = nwinfo->volume; 127} 128 129void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) 130{ 131 ncp_update_dirent(inode, nwinfo); 132 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; 133 NCP_FINFO(inode)->access = nwinfo->access; 134 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, 135 sizeof(nwinfo->file_handle)); 136 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n", 137 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, 138 NCP_FINFO(inode)->dirEntNum); 139} 140 141static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) 142{ 143 /* NFS namespace mode overrides others if it's set. */ 144 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n", 145 nwi->entryName, nwi->nfs.mode); 146 if (nwi->nfs.mode) { 147 /* XXX Security? */ 148 inode->i_mode = nwi->nfs.mode; 149 } 150 151 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; 152 153 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); 154 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); 155 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); 156 inode->i_atime.tv_nsec = 0; 157 inode->i_mtime.tv_nsec = 0; 158 inode->i_ctime.tv_nsec = 0; 159} 160 161static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) 162{ 163 struct nw_info_struct *nwi = &nwinfo->i; 164 struct ncp_server *server = NCP_SERVER(inode); 165 166 if (nwi->attributes & aDIR) { 167 inode->i_mode = server->m.dir_mode; 168 /* for directories dataStreamSize seems to be some 169 Object ID ??? */ 170 i_size_write(inode, NCP_BLOCK_SIZE); 171 } else { 172 u32 size; 173 174 inode->i_mode = server->m.file_mode; 175 size = le32_to_cpu(nwi->dataStreamSize); 176 i_size_write(inode, size); 177#ifdef CONFIG_NCPFS_EXTRAS 178 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 179 && (nwi->attributes & aSHARED)) { 180 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { 181 case aHIDDEN: 182 if (server->m.flags & NCP_MOUNT_SYMLINKS) { 183 if (/* (size >= NCP_MIN_SYMLINK_SIZE) 184 && */ (size <= NCP_MAX_SYMLINK_SIZE)) { 185 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; 186 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; 187 break; 188 } 189 } 190 /* FALLTHROUGH */ 191 case 0: 192 if (server->m.flags & NCP_MOUNT_EXTRAS) 193 inode->i_mode |= S_IRUGO; 194 break; 195 case aSYSTEM: 196 if (server->m.flags & NCP_MOUNT_EXTRAS) 197 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; 198 break; 199 /* case aSYSTEM|aHIDDEN: */ 200 default: 201 /* reserved combination */ 202 break; 203 } 204 } 205#endif 206 } 207 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; 208} 209 210void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) 211{ 212 NCP_FINFO(inode)->flags = 0; 213 if (!atomic_read(&NCP_FINFO(inode)->opened)) { 214 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; 215 ncp_update_attrs(inode, nwinfo); 216 } 217 218 ncp_update_dates(inode, &nwinfo->i); 219 ncp_update_dirent(inode, nwinfo); 220} 221 222/* 223 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. 224 */ 225static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) 226{ 227 struct ncp_server *server = NCP_SERVER(inode); 228 229 NCP_FINFO(inode)->flags = 0; 230 231 ncp_update_attrs(inode, nwinfo); 232 233 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); 234 235 set_nlink(inode, 1); 236 inode->i_uid = server->m.uid; 237 inode->i_gid = server->m.gid; 238 239 ncp_update_dates(inode, &nwinfo->i); 240 ncp_update_inode(inode, nwinfo); 241} 242 243#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 244static const struct inode_operations ncp_symlink_inode_operations = { 245 .readlink = generic_readlink, 246 .follow_link = page_follow_link_light, 247 .put_link = page_put_link, 248 .setattr = ncp_notify_change, 249}; 250#endif 251 252/* 253 * Get a new inode. 254 */ 255struct inode * 256ncp_iget(struct super_block *sb, struct ncp_entry_info *info) 257{ 258 struct inode *inode; 259 260 if (info == NULL) { 261 printk(KERN_ERR "ncp_iget: info is NULL\n"); 262 return NULL; 263 } 264 265 inode = new_inode(sb); 266 if (inode) { 267 atomic_set(&NCP_FINFO(inode)->opened, info->opened); 268 269 inode->i_mapping->backing_dev_info = sb->s_bdi; 270 inode->i_ino = info->ino; 271 ncp_set_attr(inode, info); 272 if (S_ISREG(inode->i_mode)) { 273 inode->i_op = &ncp_file_inode_operations; 274 inode->i_fop = &ncp_file_operations; 275 } else if (S_ISDIR(inode->i_mode)) { 276 inode->i_op = &ncp_dir_inode_operations; 277 inode->i_fop = &ncp_dir_operations; 278#ifdef CONFIG_NCPFS_NFS_NS 279 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 280 init_special_inode(inode, inode->i_mode, 281 new_decode_dev(info->i.nfs.rdev)); 282#endif 283#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 284 } else if (S_ISLNK(inode->i_mode)) { 285 inode->i_op = &ncp_symlink_inode_operations; 286 inode->i_data.a_ops = &ncp_symlink_aops; 287#endif 288 } else { 289 make_bad_inode(inode); 290 } 291 insert_inode_hash(inode); 292 } else 293 printk(KERN_ERR "ncp_iget: iget failed!\n"); 294 return inode; 295} 296 297static void 298ncp_evict_inode(struct inode *inode) 299{ 300 truncate_inode_pages(&inode->i_data, 0); 301 clear_inode(inode); 302 303 if (S_ISDIR(inode->i_mode)) { 304 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino); 305 } 306 307 if (ncp_make_closed(inode) != 0) { 308 /* We can't do anything but complain. */ 309 printk(KERN_ERR "ncp_evict_inode: could not close\n"); 310 } 311} 312 313static void ncp_stop_tasks(struct ncp_server *server) { 314 struct sock* sk = server->ncp_sock->sk; 315 316 lock_sock(sk); 317 sk->sk_error_report = server->error_report; 318 sk->sk_data_ready = server->data_ready; 319 sk->sk_write_space = server->write_space; 320 release_sock(sk); 321 del_timer_sync(&server->timeout_tm); 322 323 flush_work(&server->rcv.tq); 324 if (sk->sk_socket->type == SOCK_STREAM) 325 flush_work(&server->tx.tq); 326 else 327 flush_work(&server->timeout_tq); 328} 329 330static int ncp_show_options(struct seq_file *seq, struct dentry *root) 331{ 332 struct ncp_server *server = NCP_SBP(root->d_sb); 333 unsigned int tmp; 334 335 if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID)) 336 seq_printf(seq, ",uid=%u", 337 from_kuid_munged(&init_user_ns, server->m.uid)); 338 if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID)) 339 seq_printf(seq, ",gid=%u", 340 from_kgid_munged(&init_user_ns, server->m.gid)); 341 if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID)) 342 seq_printf(seq, ",owner=%u", 343 from_kuid_munged(&init_user_ns, server->m.mounted_uid)); 344 tmp = server->m.file_mode & S_IALLUGO; 345 if (tmp != NCP_DEFAULT_FILE_MODE) 346 seq_printf(seq, ",mode=0%o", tmp); 347 tmp = server->m.dir_mode & S_IALLUGO; 348 if (tmp != NCP_DEFAULT_DIR_MODE) 349 seq_printf(seq, ",dirmode=0%o", tmp); 350 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) { 351 tmp = server->m.time_out * 100 / HZ; 352 seq_printf(seq, ",timeout=%u", tmp); 353 } 354 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT) 355 seq_printf(seq, ",retry=%u", server->m.retry_count); 356 if (server->m.flags != 0) 357 seq_printf(seq, ",flags=%lu", server->m.flags); 358 if (server->m.wdog_pid != NULL) 359 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid)); 360 361 return 0; 362} 363 364static const struct ncp_option ncp_opts[] = { 365 { "uid", OPT_INT, 'u' }, 366 { "gid", OPT_INT, 'g' }, 367 { "owner", OPT_INT, 'o' }, 368 { "mode", OPT_INT, 'm' }, 369 { "dirmode", OPT_INT, 'd' }, 370 { "timeout", OPT_INT, 't' }, 371 { "retry", OPT_INT, 'r' }, 372 { "flags", OPT_INT, 'f' }, 373 { "wdogpid", OPT_INT, 'w' }, 374 { "ncpfd", OPT_INT, 'n' }, 375 { "infofd", OPT_INT, 'i' }, /* v5 */ 376 { "version", OPT_INT, 'v' }, 377 { NULL, 0, 0 } }; 378 379static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { 380 int optval; 381 char *optarg; 382 unsigned long optint; 383 int version = 0; 384 int ret; 385 386 data->flags = 0; 387 data->int_flags = 0; 388 data->mounted_uid = GLOBAL_ROOT_UID; 389 data->wdog_pid = NULL; 390 data->ncp_fd = ~0; 391 data->time_out = NCP_DEFAULT_TIME_OUT; 392 data->retry_count = NCP_DEFAULT_RETRY_COUNT; 393 data->uid = GLOBAL_ROOT_UID; 394 data->gid = GLOBAL_ROOT_GID; 395 data->file_mode = NCP_DEFAULT_FILE_MODE; 396 data->dir_mode = NCP_DEFAULT_DIR_MODE; 397 data->info_fd = -1; 398 data->mounted_vol[0] = 0; 399 400 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { 401 ret = optval; 402 if (ret < 0) 403 goto err; 404 switch (optval) { 405 case 'u': 406 data->uid = make_kuid(current_user_ns(), optint); 407 if (!uid_valid(data->uid)) { 408 ret = -EINVAL; 409 goto err; 410 } 411 break; 412 case 'g': 413 data->gid = make_kgid(current_user_ns(), optint); 414 if (!gid_valid(data->gid)) { 415 ret = -EINVAL; 416 goto err; 417 } 418 break; 419 case 'o': 420 data->mounted_uid = make_kuid(current_user_ns(), optint); 421 if (!uid_valid(data->mounted_uid)) { 422 ret = -EINVAL; 423 goto err; 424 } 425 break; 426 case 'm': 427 data->file_mode = optint; 428 break; 429 case 'd': 430 data->dir_mode = optint; 431 break; 432 case 't': 433 data->time_out = optint; 434 break; 435 case 'r': 436 data->retry_count = optint; 437 break; 438 case 'f': 439 data->flags = optint; 440 break; 441 case 'w': 442 data->wdog_pid = find_get_pid(optint); 443 break; 444 case 'n': 445 data->ncp_fd = optint; 446 break; 447 case 'i': 448 data->info_fd = optint; 449 break; 450 case 'v': 451 ret = -ECHRNG; 452 if (optint < NCP_MOUNT_VERSION_V4) 453 goto err; 454 if (optint > NCP_MOUNT_VERSION_V5) 455 goto err; 456 version = optint; 457 break; 458 459 } 460 } 461 return 0; 462err: 463 put_pid(data->wdog_pid); 464 data->wdog_pid = NULL; 465 return ret; 466} 467 468static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) 469{ 470 struct ncp_mount_data_kernel data; 471 struct ncp_server *server; 472 struct file *ncp_filp; 473 struct inode *root_inode; 474 struct inode *sock_inode; 475 struct socket *sock; 476 int error; 477 int default_bufsize; 478#ifdef CONFIG_NCPFS_PACKET_SIGNING 479 int options; 480#endif 481 struct ncp_entry_info finfo; 482 483 memset(&data, 0, sizeof(data)); 484 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); 485 if (!server) 486 return -ENOMEM; 487 sb->s_fs_info = server; 488 489 error = -EFAULT; 490 if (raw_data == NULL) 491 goto out; 492 switch (*(int*)raw_data) { 493 case NCP_MOUNT_VERSION: 494 { 495 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; 496 497 data.flags = md->flags; 498 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; 499 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); 500 data.wdog_pid = find_get_pid(md->wdog_pid); 501 data.ncp_fd = md->ncp_fd; 502 data.time_out = md->time_out; 503 data.retry_count = md->retry_count; 504 data.uid = make_kuid(current_user_ns(), md->uid); 505 data.gid = make_kgid(current_user_ns(), md->gid); 506 data.file_mode = md->file_mode; 507 data.dir_mode = md->dir_mode; 508 data.info_fd = -1; 509 memcpy(data.mounted_vol, md->mounted_vol, 510 NCP_VOLNAME_LEN+1); 511 } 512 break; 513 case NCP_MOUNT_VERSION_V4: 514 { 515 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; 516 517 data.flags = md->flags; 518 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); 519 data.wdog_pid = find_get_pid(md->wdog_pid); 520 data.ncp_fd = md->ncp_fd; 521 data.time_out = md->time_out; 522 data.retry_count = md->retry_count; 523 data.uid = make_kuid(current_user_ns(), md->uid); 524 data.gid = make_kgid(current_user_ns(), md->gid); 525 data.file_mode = md->file_mode; 526 data.dir_mode = md->dir_mode; 527 data.info_fd = -1; 528 } 529 break; 530 default: 531 error = -ECHRNG; 532 if (memcmp(raw_data, "vers", 4) == 0) { 533 error = ncp_parse_options(&data, raw_data); 534 } 535 if (error) 536 goto out; 537 break; 538 } 539 error = -EINVAL; 540 if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || 541 !gid_valid(data.gid)) 542 goto out; 543 error = -EBADF; 544 ncp_filp = fget(data.ncp_fd); 545 if (!ncp_filp) 546 goto out; 547 error = -ENOTSOCK; 548 sock_inode = file_inode(ncp_filp); 549 if (!S_ISSOCK(sock_inode->i_mode)) 550 goto out_fput; 551 sock = SOCKET_I(sock_inode); 552 if (!sock) 553 goto out_fput; 554 555 if (sock->type == SOCK_STREAM) 556 default_bufsize = 0xF000; 557 else 558 default_bufsize = 1024; 559 560 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ 561 sb->s_maxbytes = 0xFFFFFFFFU; 562 sb->s_blocksize = 1024; /* Eh... Is this correct? */ 563 sb->s_blocksize_bits = 10; 564 sb->s_magic = NCP_SUPER_MAGIC; 565 sb->s_op = &ncp_sops; 566 sb->s_d_op = &ncp_dentry_operations; 567 sb->s_bdi = &server->bdi; 568 569 server = NCP_SBP(sb); 570 memset(server, 0, sizeof(*server)); 571 572 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); 573 if (error) 574 goto out_fput; 575 576 server->ncp_filp = ncp_filp; 577 server->ncp_sock = sock; 578 579 if (data.info_fd != -1) { 580 struct socket *info_sock; 581 582 error = -EBADF; 583 server->info_filp = fget(data.info_fd); 584 if (!server->info_filp) 585 goto out_bdi; 586 error = -ENOTSOCK; 587 sock_inode = file_inode(server->info_filp); 588 if (!S_ISSOCK(sock_inode->i_mode)) 589 goto out_fput2; 590 info_sock = SOCKET_I(sock_inode); 591 if (!info_sock) 592 goto out_fput2; 593 error = -EBADFD; 594 if (info_sock->type != SOCK_STREAM) 595 goto out_fput2; 596 server->info_sock = info_sock; 597 } 598 599/* server->lock = 0; */ 600 mutex_init(&server->mutex); 601 server->packet = NULL; 602/* server->buffer_size = 0; */ 603/* server->conn_status = 0; */ 604/* server->root_dentry = NULL; */ 605/* server->root_setuped = 0; */ 606 mutex_init(&server->root_setup_lock); 607#ifdef CONFIG_NCPFS_PACKET_SIGNING 608/* server->sign_wanted = 0; */ 609/* server->sign_active = 0; */ 610#endif 611 init_rwsem(&server->auth_rwsem); 612 server->auth.auth_type = NCP_AUTH_NONE; 613/* server->auth.object_name_len = 0; */ 614/* server->auth.object_name = NULL; */ 615/* server->auth.object_type = 0; */ 616/* server->priv.len = 0; */ 617/* server->priv.data = NULL; */ 618 619 server->m = data; 620 /* Although anything producing this is buggy, it happens 621 now because of PATH_MAX changes.. */ 622 if (server->m.time_out < 1) { 623 server->m.time_out = 10; 624 printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); 625 } 626 server->m.time_out = server->m.time_out * HZ / 100; 627 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; 628 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; 629 630#ifdef CONFIG_NCPFS_NLS 631 /* load the default NLS charsets */ 632 server->nls_vol = load_nls_default(); 633 server->nls_io = load_nls_default(); 634#endif /* CONFIG_NCPFS_NLS */ 635 636 atomic_set(&server->dentry_ttl, 0); /* no caching */ 637 638 INIT_LIST_HEAD(&server->tx.requests); 639 mutex_init(&server->rcv.creq_mutex); 640 server->tx.creq = NULL; 641 server->rcv.creq = NULL; 642 643 init_timer(&server->timeout_tm); 644#undef NCP_PACKET_SIZE 645#define NCP_PACKET_SIZE 131072 646 error = -ENOMEM; 647 server->packet_size = NCP_PACKET_SIZE; 648 server->packet = vmalloc(NCP_PACKET_SIZE); 649 if (server->packet == NULL) 650 goto out_nls; 651 server->txbuf = vmalloc(NCP_PACKET_SIZE); 652 if (server->txbuf == NULL) 653 goto out_packet; 654 server->rxbuf = vmalloc(NCP_PACKET_SIZE); 655 if (server->rxbuf == NULL) 656 goto out_txbuf; 657 658 lock_sock(sock->sk); 659 server->data_ready = sock->sk->sk_data_ready; 660 server->write_space = sock->sk->sk_write_space; 661 server->error_report = sock->sk->sk_error_report; 662 sock->sk->sk_user_data = server; 663 sock->sk->sk_data_ready = ncp_tcp_data_ready; 664 sock->sk->sk_error_report = ncp_tcp_error_report; 665 if (sock->type == SOCK_STREAM) { 666 server->rcv.ptr = (unsigned char*)&server->rcv.buf; 667 server->rcv.len = 10; 668 server->rcv.state = 0; 669 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); 670 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); 671 sock->sk->sk_write_space = ncp_tcp_write_space; 672 } else { 673 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); 674 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); 675 server->timeout_tm.data = (unsigned long)server; 676 server->timeout_tm.function = ncpdgram_timeout_call; 677 } 678 release_sock(sock->sk); 679 680 ncp_lock_server(server); 681 error = ncp_connect(server); 682 ncp_unlock_server(server); 683 if (error < 0) 684 goto out_rxbuf; 685 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); 686 687 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ 688#ifdef CONFIG_NCPFS_PACKET_SIGNING 689 if (ncp_negotiate_size_and_options(server, default_bufsize, 690 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) 691 { 692 if (options != NCP_DEFAULT_OPTIONS) 693 { 694 if (ncp_negotiate_size_and_options(server, 695 default_bufsize, 696 options & 2, 697 &(server->buffer_size), &options) != 0) 698 699 { 700 goto out_disconnect; 701 } 702 } 703 ncp_lock_server(server); 704 if (options & 2) 705 server->sign_wanted = 1; 706 ncp_unlock_server(server); 707 } 708 else 709#endif /* CONFIG_NCPFS_PACKET_SIGNING */ 710 if (ncp_negotiate_buffersize(server, default_bufsize, 711 &(server->buffer_size)) != 0) 712 goto out_disconnect; 713 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); 714 715 memset(&finfo, 0, sizeof(finfo)); 716 finfo.i.attributes = aDIR; 717 finfo.i.dataStreamSize = 0; /* ignored */ 718 finfo.i.dirEntNum = 0; 719 finfo.i.DosDirNum = 0; 720#ifdef CONFIG_NCPFS_SMALLDOS 721 finfo.i.NSCreator = NW_NS_DOS; 722#endif 723 finfo.volume = NCP_NUMBER_OF_VOLUMES; 724 /* set dates of mountpoint to Jan 1, 1986; 00:00 */ 725 finfo.i.creationTime = finfo.i.modifyTime 726 = cpu_to_le16(0x0000); 727 finfo.i.creationDate = finfo.i.modifyDate 728 = finfo.i.lastAccessDate 729 = cpu_to_le16(0x0C21); 730 finfo.i.nameLen = 0; 731 finfo.i.entryName[0] = '\0'; 732 733 finfo.opened = 0; 734 finfo.ino = 2; /* tradition */ 735 736 server->name_space[finfo.volume] = NW_NS_DOS; 737 738 error = -ENOMEM; 739 root_inode = ncp_iget(sb, &finfo); 740 if (!root_inode) 741 goto out_disconnect; 742 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); 743 sb->s_root = d_make_root(root_inode); 744 if (!sb->s_root) 745 goto out_disconnect; 746 return 0; 747 748out_disconnect: 749 ncp_lock_server(server); 750 ncp_disconnect(server); 751 ncp_unlock_server(server); 752out_rxbuf: 753 ncp_stop_tasks(server); 754 vfree(server->rxbuf); 755out_txbuf: 756 vfree(server->txbuf); 757out_packet: 758 vfree(server->packet); 759out_nls: 760#ifdef CONFIG_NCPFS_NLS 761 unload_nls(server->nls_io); 762 unload_nls(server->nls_vol); 763#endif 764 mutex_destroy(&server->rcv.creq_mutex); 765 mutex_destroy(&server->root_setup_lock); 766 mutex_destroy(&server->mutex); 767out_fput2: 768 if (server->info_filp) 769 fput(server->info_filp); 770out_bdi: 771 bdi_destroy(&server->bdi); 772out_fput: 773 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: 774 * 775 * The previously used put_filp(ncp_filp); was bogus, since 776 * it doesn't perform proper unlocking. 777 */ 778 fput(ncp_filp); 779out: 780 put_pid(data.wdog_pid); 781 sb->s_fs_info = NULL; 782 kfree(server); 783 return error; 784} 785 786static void delayed_free(struct rcu_head *p) 787{ 788 struct ncp_server *server = container_of(p, struct ncp_server, rcu); 789#ifdef CONFIG_NCPFS_NLS 790 /* unload the NLS charsets */ 791 unload_nls(server->nls_vol); 792 unload_nls(server->nls_io); 793#endif /* CONFIG_NCPFS_NLS */ 794 kfree(server); 795} 796 797static void ncp_put_super(struct super_block *sb) 798{ 799 struct ncp_server *server = NCP_SBP(sb); 800 801 ncp_lock_server(server); 802 ncp_disconnect(server); 803 ncp_unlock_server(server); 804 805 ncp_stop_tasks(server); 806 807 mutex_destroy(&server->rcv.creq_mutex); 808 mutex_destroy(&server->root_setup_lock); 809 mutex_destroy(&server->mutex); 810 811 if (server->info_filp) 812 fput(server->info_filp); 813 fput(server->ncp_filp); 814 kill_pid(server->m.wdog_pid, SIGTERM, 1); 815 put_pid(server->m.wdog_pid); 816 817 bdi_destroy(&server->bdi); 818 kfree(server->priv.data); 819 kfree(server->auth.object_name); 820 vfree(server->rxbuf); 821 vfree(server->txbuf); 822 vfree(server->packet); 823 call_rcu(&server->rcu, delayed_free); 824} 825 826static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) 827{ 828 struct dentry* d; 829 struct inode* i; 830 struct ncp_inode_info* ni; 831 struct ncp_server* s; 832 struct ncp_volume_info vi; 833 struct super_block *sb = dentry->d_sb; 834 int err; 835 __u8 dh; 836 837 d = sb->s_root; 838 if (!d) { 839 goto dflt; 840 } 841 i = d->d_inode; 842 if (!i) { 843 goto dflt; 844 } 845 ni = NCP_FINFO(i); 846 if (!ni) { 847 goto dflt; 848 } 849 s = NCP_SBP(sb); 850 if (!s) { 851 goto dflt; 852 } 853 if (!s->m.mounted_vol[0]) { 854 goto dflt; 855 } 856 857 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); 858 if (err) { 859 goto dflt; 860 } 861 err = ncp_get_directory_info(s, dh, &vi); 862 ncp_dirhandle_free(s, dh); 863 if (err) { 864 goto dflt; 865 } 866 buf->f_type = NCP_SUPER_MAGIC; 867 buf->f_bsize = vi.sectors_per_block * 512; 868 buf->f_blocks = vi.total_blocks; 869 buf->f_bfree = vi.free_blocks; 870 buf->f_bavail = vi.free_blocks; 871 buf->f_files = vi.total_dir_entries; 872 buf->f_ffree = vi.available_dir_entries; 873 buf->f_namelen = 12; 874 return 0; 875 876 /* We cannot say how much disk space is left on a mounted 877 NetWare Server, because free space is distributed over 878 volumes, and the current user might have disk quotas. So 879 free space is not that simple to determine. Our decision 880 here is to err conservatively. */ 881 882dflt:; 883 buf->f_type = NCP_SUPER_MAGIC; 884 buf->f_bsize = NCP_BLOCK_SIZE; 885 buf->f_blocks = 0; 886 buf->f_bfree = 0; 887 buf->f_bavail = 0; 888 buf->f_namelen = 12; 889 return 0; 890} 891 892int ncp_notify_change(struct dentry *dentry, struct iattr *attr) 893{ 894 struct inode *inode = dentry->d_inode; 895 int result = 0; 896 __le32 info_mask; 897 struct nw_modify_dos_info info; 898 struct ncp_server *server; 899 900 result = -EIO; 901 902 server = NCP_SERVER(inode); 903 if (!server) /* How this could happen? */ 904 goto out; 905 906 result = -EPERM; 907 if (IS_DEADDIR(dentry->d_inode)) 908 goto out; 909 910 /* ageing the dentry to force validation */ 911 ncp_age_dentry(server, dentry); 912 913 result = inode_change_ok(inode, attr); 914 if (result < 0) 915 goto out; 916 917 result = -EPERM; 918 if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid)) 919 goto out; 920 921 if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid)) 922 goto out; 923 924 if (((attr->ia_valid & ATTR_MODE) && 925 (attr->ia_mode & 926 ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) 927 goto out; 928 929 info_mask = 0; 930 memset(&info, 0, sizeof(info)); 931 932#if 1 933 if ((attr->ia_valid & ATTR_MODE) != 0) 934 { 935 umode_t newmode = attr->ia_mode; 936 937 info_mask |= DM_ATTRIBUTES; 938 939 if (S_ISDIR(inode->i_mode)) { 940 newmode &= server->m.dir_mode; 941 } else { 942#ifdef CONFIG_NCPFS_EXTRAS 943 if (server->m.flags & NCP_MOUNT_EXTRAS) { 944 /* any non-default execute bit set */ 945 if (newmode & ~server->m.file_mode & S_IXUGO) 946 info.attributes |= aSHARED | aSYSTEM; 947 /* read for group/world and not in default file_mode */ 948 else if (newmode & ~server->m.file_mode & S_IRUGO) 949 info.attributes |= aSHARED; 950 } else 951#endif 952 newmode &= server->m.file_mode; 953 } 954 if (newmode & S_IWUGO) 955 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 956 else 957 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 958 959#ifdef CONFIG_NCPFS_NFS_NS 960 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { 961 result = ncp_modify_nfs_info(server, 962 NCP_FINFO(inode)->volNumber, 963 NCP_FINFO(inode)->dirEntNum, 964 attr->ia_mode, 0); 965 if (result != 0) 966 goto out; 967 info.attributes &= ~(aSHARED | aSYSTEM); 968 { 969 /* mark partial success */ 970 struct iattr tmpattr; 971 972 tmpattr.ia_valid = ATTR_MODE; 973 tmpattr.ia_mode = attr->ia_mode; 974 975 setattr_copy(inode, &tmpattr); 976 mark_inode_dirty(inode); 977 } 978 } 979#endif 980 } 981#endif 982 983 /* Do SIZE before attributes, otherwise mtime together with size does not work... 984 */ 985 if ((attr->ia_valid & ATTR_SIZE) != 0) { 986 int written; 987 988 DPRINTK("ncpfs: trying to change size to %ld\n", 989 attr->ia_size); 990 991 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { 992 result = -EACCES; 993 goto out; 994 } 995 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 996 attr->ia_size, 0, "", &written); 997 998 /* According to ndir, the changes only take effect after 999 closing the file */ 1000 ncp_inode_close(inode); 1001 result = ncp_make_closed(inode); 1002 if (result) 1003 goto out; 1004 1005 if (attr->ia_size != i_size_read(inode)) { 1006 truncate_setsize(inode, attr->ia_size); 1007 mark_inode_dirty(inode); 1008 } 1009 } 1010 if ((attr->ia_valid & ATTR_CTIME) != 0) { 1011 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); 1012 ncp_date_unix2dos(attr->ia_ctime.tv_sec, 1013 &info.creationTime, &info.creationDate); 1014 } 1015 if ((attr->ia_valid & ATTR_MTIME) != 0) { 1016 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); 1017 ncp_date_unix2dos(attr->ia_mtime.tv_sec, 1018 &info.modifyTime, &info.modifyDate); 1019 } 1020 if ((attr->ia_valid & ATTR_ATIME) != 0) { 1021 __le16 dummy; 1022 info_mask |= (DM_LAST_ACCESS_DATE); 1023 ncp_date_unix2dos(attr->ia_atime.tv_sec, 1024 &dummy, &info.lastAccessDate); 1025 } 1026 if (info_mask != 0) { 1027 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), 1028 inode, info_mask, &info); 1029 if (result != 0) { 1030 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { 1031 /* NetWare seems not to allow this. I 1032 do not know why. So, just tell the 1033 user everything went fine. This is 1034 a terrible hack, but I do not know 1035 how to do this correctly. */ 1036 result = 0; 1037 } else 1038 goto out; 1039 } 1040#ifdef CONFIG_NCPFS_STRONG 1041 if ((!result) && (info_mask & DM_ATTRIBUTES)) 1042 NCP_FINFO(inode)->nwattr = info.attributes; 1043#endif 1044 } 1045 if (result) 1046 goto out; 1047 1048 setattr_copy(inode, attr); 1049 mark_inode_dirty(inode); 1050 1051out: 1052 if (result > 0) 1053 result = -EACCES; 1054 return result; 1055} 1056 1057static struct dentry *ncp_mount(struct file_system_type *fs_type, 1058 int flags, const char *dev_name, void *data) 1059{ 1060 return mount_nodev(fs_type, flags, data, ncp_fill_super); 1061} 1062 1063static struct file_system_type ncp_fs_type = { 1064 .owner = THIS_MODULE, 1065 .name = "ncpfs", 1066 .mount = ncp_mount, 1067 .kill_sb = kill_anon_super, 1068 .fs_flags = FS_BINARY_MOUNTDATA, 1069}; 1070MODULE_ALIAS_FS("ncpfs"); 1071 1072static int __init init_ncp_fs(void) 1073{ 1074 int err; 1075 DPRINTK("ncpfs: init_ncp_fs called\n"); 1076 1077 err = init_inodecache(); 1078 if (err) 1079 goto out1; 1080 err = register_filesystem(&ncp_fs_type); 1081 if (err) 1082 goto out; 1083 return 0; 1084out: 1085 destroy_inodecache(); 1086out1: 1087 return err; 1088} 1089 1090static void __exit exit_ncp_fs(void) 1091{ 1092 DPRINTK("ncpfs: exit_ncp_fs called\n"); 1093 unregister_filesystem(&ncp_fs_type); 1094 destroy_inodecache(); 1095} 1096 1097module_init(init_ncp_fs) 1098module_exit(exit_ncp_fs) 1099MODULE_LICENSE("GPL"); 1100