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