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
12 #include <linux/module.h>
14 #include <asm/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
18 #include <linux/time.h>
19 #include <linux/kernel.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/vfs.h>
30 #include <linux/mount.h>
31 #include <linux/seq_file.h>
32 #include <linux/namei.h>
34 #include <linux/ncp_fs.h>
38 #include "ncplib_kernel.h"
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
46 static void ncp_evict_inode(struct inode *);
47 static void ncp_put_super(struct super_block *);
48 static int ncp_statfs(struct dentry *, struct kstatfs *);
49 static int ncp_show_options(struct seq_file *, struct vfsmount *);
51 static struct kmem_cache * ncp_inode_cachep;
53 static struct inode *ncp_alloc_inode(struct super_block *sb)
55 struct ncp_inode_info *ei;
56 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
59 return &ei->vfs_inode;
62 static void ncp_i_callback(struct rcu_head *head)
64 struct inode *inode = container_of(head, struct inode, i_rcu);
65 INIT_LIST_HEAD(&inode->i_dentry);
66 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
69 static void ncp_destroy_inode(struct inode *inode)
71 call_rcu(&inode->i_rcu, ncp_i_callback);
74 static void init_once(void *foo)
76 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
78 mutex_init(&ei->open_mutex);
79 inode_init_once(&ei->vfs_inode);
82 static int init_inodecache(void)
84 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
85 sizeof(struct ncp_inode_info),
86 0, (SLAB_RECLAIM_ACCOUNT|
89 if (ncp_inode_cachep == NULL)
94 static void destroy_inodecache(void)
96 kmem_cache_destroy(ncp_inode_cachep);
99 static int ncp_remount(struct super_block *sb, int *flags, char* data)
101 *flags |= MS_NODIRATIME;
105 static const struct super_operations ncp_sops =
107 .alloc_inode = ncp_alloc_inode,
108 .destroy_inode = ncp_destroy_inode,
109 .drop_inode = generic_delete_inode,
110 .evict_inode = ncp_evict_inode,
111 .put_super = ncp_put_super,
112 .statfs = ncp_statfs,
113 .remount_fs = ncp_remount,
114 .show_options = ncp_show_options,
118 * Fill in the ncpfs-specific information in the inode.
120 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
122 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
123 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
124 NCP_FINFO(inode)->volNumber = nwinfo->volume;
127 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
129 ncp_update_dirent(inode, nwinfo);
130 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
131 NCP_FINFO(inode)->access = nwinfo->access;
132 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
133 sizeof(nwinfo->file_handle));
134 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
135 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
136 NCP_FINFO(inode)->dirEntNum);
139 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
141 /* NFS namespace mode overrides others if it's set. */
142 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
143 nwi->entryName, nwi->nfs.mode);
146 inode->i_mode = nwi->nfs.mode;
149 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
151 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
152 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
153 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
154 inode->i_atime.tv_nsec = 0;
155 inode->i_mtime.tv_nsec = 0;
156 inode->i_ctime.tv_nsec = 0;
159 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
161 struct nw_info_struct *nwi = &nwinfo->i;
162 struct ncp_server *server = NCP_SERVER(inode);
164 if (nwi->attributes & aDIR) {
165 inode->i_mode = server->m.dir_mode;
166 /* for directories dataStreamSize seems to be some
168 i_size_write(inode, NCP_BLOCK_SIZE);
172 inode->i_mode = server->m.file_mode;
173 size = le32_to_cpu(nwi->dataStreamSize);
174 i_size_write(inode, size);
175 #ifdef CONFIG_NCPFS_EXTRAS
176 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
177 && (nwi->attributes & aSHARED)) {
178 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
180 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
181 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
182 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
183 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
184 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
190 if (server->m.flags & NCP_MOUNT_EXTRAS)
191 inode->i_mode |= S_IRUGO;
194 if (server->m.flags & NCP_MOUNT_EXTRAS)
195 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
197 /* case aSYSTEM|aHIDDEN: */
199 /* reserved combination */
205 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
208 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
210 NCP_FINFO(inode)->flags = 0;
211 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
212 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
213 ncp_update_attrs(inode, nwinfo);
216 ncp_update_dates(inode, &nwinfo->i);
217 ncp_update_dirent(inode, nwinfo);
221 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
223 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
225 struct ncp_server *server = NCP_SERVER(inode);
227 NCP_FINFO(inode)->flags = 0;
229 ncp_update_attrs(inode, nwinfo);
231 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
234 inode->i_uid = server->m.uid;
235 inode->i_gid = server->m.gid;
237 ncp_update_dates(inode, &nwinfo->i);
238 ncp_update_inode(inode, nwinfo);
241 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
242 static const struct inode_operations ncp_symlink_inode_operations = {
243 .readlink = generic_readlink,
244 .follow_link = page_follow_link_light,
245 .put_link = page_put_link,
246 .setattr = ncp_notify_change,
254 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
259 printk(KERN_ERR "ncp_iget: info is NULL\n");
263 inode = new_inode(sb);
265 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
267 inode->i_mapping->backing_dev_info = sb->s_bdi;
268 inode->i_ino = info->ino;
269 ncp_set_attr(inode, info);
270 if (S_ISREG(inode->i_mode)) {
271 inode->i_op = &ncp_file_inode_operations;
272 inode->i_fop = &ncp_file_operations;
273 } else if (S_ISDIR(inode->i_mode)) {
274 inode->i_op = &ncp_dir_inode_operations;
275 inode->i_fop = &ncp_dir_operations;
276 #ifdef CONFIG_NCPFS_NFS_NS
277 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
278 init_special_inode(inode, inode->i_mode,
279 new_decode_dev(info->i.nfs.rdev));
281 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
282 } else if (S_ISLNK(inode->i_mode)) {
283 inode->i_op = &ncp_symlink_inode_operations;
284 inode->i_data.a_ops = &ncp_symlink_aops;
287 make_bad_inode(inode);
289 insert_inode_hash(inode);
291 printk(KERN_ERR "ncp_iget: iget failed!\n");
296 ncp_evict_inode(struct inode *inode)
298 truncate_inode_pages(&inode->i_data, 0);
299 end_writeback(inode);
301 if (S_ISDIR(inode->i_mode)) {
302 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
305 if (ncp_make_closed(inode) != 0) {
306 /* We can't do anything but complain. */
307 printk(KERN_ERR "ncp_evict_inode: could not close\n");
311 static void ncp_stop_tasks(struct ncp_server *server) {
312 struct sock* sk = server->ncp_sock->sk;
315 sk->sk_error_report = server->error_report;
316 sk->sk_data_ready = server->data_ready;
317 sk->sk_write_space = server->write_space;
319 del_timer_sync(&server->timeout_tm);
321 flush_work_sync(&server->rcv.tq);
322 if (sk->sk_socket->type == SOCK_STREAM)
323 flush_work_sync(&server->tx.tq);
325 flush_work_sync(&server->timeout_tq);
328 static int ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
330 struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
333 if (server->m.uid != 0)
334 seq_printf(seq, ",uid=%u", server->m.uid);
335 if (server->m.gid != 0)
336 seq_printf(seq, ",gid=%u", server->m.gid);
337 if (server->m.mounted_uid != 0)
338 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
339 tmp = server->m.file_mode & S_IALLUGO;
340 if (tmp != NCP_DEFAULT_FILE_MODE)
341 seq_printf(seq, ",mode=0%o", tmp);
342 tmp = server->m.dir_mode & S_IALLUGO;
343 if (tmp != NCP_DEFAULT_DIR_MODE)
344 seq_printf(seq, ",dirmode=0%o", tmp);
345 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
346 tmp = server->m.time_out * 100 / HZ;
347 seq_printf(seq, ",timeout=%u", tmp);
349 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
350 seq_printf(seq, ",retry=%u", server->m.retry_count);
351 if (server->m.flags != 0)
352 seq_printf(seq, ",flags=%lu", server->m.flags);
353 if (server->m.wdog_pid != NULL)
354 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
359 static const struct ncp_option ncp_opts[] = {
360 { "uid", OPT_INT, 'u' },
361 { "gid", OPT_INT, 'g' },
362 { "owner", OPT_INT, 'o' },
363 { "mode", OPT_INT, 'm' },
364 { "dirmode", OPT_INT, 'd' },
365 { "timeout", OPT_INT, 't' },
366 { "retry", OPT_INT, 'r' },
367 { "flags", OPT_INT, 'f' },
368 { "wdogpid", OPT_INT, 'w' },
369 { "ncpfd", OPT_INT, 'n' },
370 { "infofd", OPT_INT, 'i' }, /* v5 */
371 { "version", OPT_INT, 'v' },
374 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
377 unsigned long optint;
383 data->mounted_uid = 0;
384 data->wdog_pid = NULL;
386 data->time_out = NCP_DEFAULT_TIME_OUT;
387 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
390 data->file_mode = NCP_DEFAULT_FILE_MODE;
391 data->dir_mode = NCP_DEFAULT_DIR_MODE;
393 data->mounted_vol[0] = 0;
395 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
407 data->mounted_uid = optint;
410 data->file_mode = optint;
413 data->dir_mode = optint;
416 data->time_out = optint;
419 data->retry_count = optint;
422 data->flags = optint;
425 data->wdog_pid = find_get_pid(optint);
428 data->ncp_fd = optint;
431 data->info_fd = optint;
435 if (optint < NCP_MOUNT_VERSION_V4)
437 if (optint > NCP_MOUNT_VERSION_V5)
446 put_pid(data->wdog_pid);
447 data->wdog_pid = NULL;
451 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
453 struct ncp_mount_data_kernel data;
454 struct ncp_server *server;
455 struct file *ncp_filp;
456 struct inode *root_inode;
457 struct inode *sock_inode;
461 #ifdef CONFIG_NCPFS_PACKET_SIGNING
464 struct ncp_entry_info finfo;
466 data.wdog_pid = NULL;
467 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
470 sb->s_fs_info = server;
473 if (raw_data == NULL)
475 switch (*(int*)raw_data) {
476 case NCP_MOUNT_VERSION:
478 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
480 data.flags = md->flags;
481 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
482 data.mounted_uid = md->mounted_uid;
483 data.wdog_pid = find_get_pid(md->wdog_pid);
484 data.ncp_fd = md->ncp_fd;
485 data.time_out = md->time_out;
486 data.retry_count = md->retry_count;
489 data.file_mode = md->file_mode;
490 data.dir_mode = md->dir_mode;
492 memcpy(data.mounted_vol, md->mounted_vol,
496 case NCP_MOUNT_VERSION_V4:
498 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
500 data.flags = md->flags;
502 data.mounted_uid = md->mounted_uid;
503 data.wdog_pid = find_get_pid(md->wdog_pid);
504 data.ncp_fd = md->ncp_fd;
505 data.time_out = md->time_out;
506 data.retry_count = md->retry_count;
509 data.file_mode = md->file_mode;
510 data.dir_mode = md->dir_mode;
512 data.mounted_vol[0] = 0;
517 if (memcmp(raw_data, "vers", 4) == 0) {
518 error = ncp_parse_options(&data, raw_data);
525 ncp_filp = fget(data.ncp_fd);
529 sock_inode = ncp_filp->f_path.dentry->d_inode;
530 if (!S_ISSOCK(sock_inode->i_mode))
532 sock = SOCKET_I(sock_inode);
536 if (sock->type == SOCK_STREAM)
537 default_bufsize = 0xF000;
539 default_bufsize = 1024;
541 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
542 sb->s_maxbytes = 0xFFFFFFFFU;
543 sb->s_blocksize = 1024; /* Eh... Is this correct? */
544 sb->s_blocksize_bits = 10;
545 sb->s_magic = NCP_SUPER_MAGIC;
546 sb->s_op = &ncp_sops;
547 sb->s_d_op = &ncp_dentry_operations;
548 sb->s_bdi = &server->bdi;
550 server = NCP_SBP(sb);
551 memset(server, 0, sizeof(*server));
553 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
557 server->ncp_filp = ncp_filp;
558 server->ncp_sock = sock;
560 if (data.info_fd != -1) {
561 struct socket *info_sock;
564 server->info_filp = fget(data.info_fd);
565 if (!server->info_filp)
568 sock_inode = server->info_filp->f_path.dentry->d_inode;
569 if (!S_ISSOCK(sock_inode->i_mode))
571 info_sock = SOCKET_I(sock_inode);
575 if (info_sock->type != SOCK_STREAM)
577 server->info_sock = info_sock;
580 /* server->lock = 0; */
581 mutex_init(&server->mutex);
582 server->packet = NULL;
583 /* server->buffer_size = 0; */
584 /* server->conn_status = 0; */
585 /* server->root_dentry = NULL; */
586 /* server->root_setuped = 0; */
587 mutex_init(&server->root_setup_lock);
588 #ifdef CONFIG_NCPFS_PACKET_SIGNING
589 /* server->sign_wanted = 0; */
590 /* server->sign_active = 0; */
592 init_rwsem(&server->auth_rwsem);
593 server->auth.auth_type = NCP_AUTH_NONE;
594 /* server->auth.object_name_len = 0; */
595 /* server->auth.object_name = NULL; */
596 /* server->auth.object_type = 0; */
597 /* server->priv.len = 0; */
598 /* server->priv.data = NULL; */
601 /* Althought anything producing this is buggy, it happens
602 now because of PATH_MAX changes.. */
603 if (server->m.time_out < 1) {
604 server->m.time_out = 10;
605 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
607 server->m.time_out = server->m.time_out * HZ / 100;
608 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
609 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
611 #ifdef CONFIG_NCPFS_NLS
612 /* load the default NLS charsets */
613 server->nls_vol = load_nls_default();
614 server->nls_io = load_nls_default();
615 #endif /* CONFIG_NCPFS_NLS */
617 atomic_set(&server->dentry_ttl, 0); /* no caching */
619 INIT_LIST_HEAD(&server->tx.requests);
620 mutex_init(&server->rcv.creq_mutex);
621 server->tx.creq = NULL;
622 server->rcv.creq = NULL;
624 init_timer(&server->timeout_tm);
625 #undef NCP_PACKET_SIZE
626 #define NCP_PACKET_SIZE 131072
628 server->packet_size = NCP_PACKET_SIZE;
629 server->packet = vmalloc(NCP_PACKET_SIZE);
630 if (server->packet == NULL)
632 server->txbuf = vmalloc(NCP_PACKET_SIZE);
633 if (server->txbuf == NULL)
635 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
636 if (server->rxbuf == NULL)
640 server->data_ready = sock->sk->sk_data_ready;
641 server->write_space = sock->sk->sk_write_space;
642 server->error_report = sock->sk->sk_error_report;
643 sock->sk->sk_user_data = server;
644 sock->sk->sk_data_ready = ncp_tcp_data_ready;
645 sock->sk->sk_error_report = ncp_tcp_error_report;
646 if (sock->type == SOCK_STREAM) {
647 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
648 server->rcv.len = 10;
649 server->rcv.state = 0;
650 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
651 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
652 sock->sk->sk_write_space = ncp_tcp_write_space;
654 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
655 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
656 server->timeout_tm.data = (unsigned long)server;
657 server->timeout_tm.function = ncpdgram_timeout_call;
659 release_sock(sock->sk);
661 ncp_lock_server(server);
662 error = ncp_connect(server);
663 ncp_unlock_server(server);
666 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
668 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
669 #ifdef CONFIG_NCPFS_PACKET_SIGNING
670 if (ncp_negotiate_size_and_options(server, default_bufsize,
671 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
673 if (options != NCP_DEFAULT_OPTIONS)
675 if (ncp_negotiate_size_and_options(server,
678 &(server->buffer_size), &options) != 0)
684 ncp_lock_server(server);
686 server->sign_wanted = 1;
687 ncp_unlock_server(server);
690 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
691 if (ncp_negotiate_buffersize(server, default_bufsize,
692 &(server->buffer_size)) != 0)
694 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
696 memset(&finfo, 0, sizeof(finfo));
697 finfo.i.attributes = aDIR;
698 finfo.i.dataStreamSize = 0; /* ignored */
699 finfo.i.dirEntNum = 0;
700 finfo.i.DosDirNum = 0;
701 #ifdef CONFIG_NCPFS_SMALLDOS
702 finfo.i.NSCreator = NW_NS_DOS;
704 finfo.volume = NCP_NUMBER_OF_VOLUMES;
705 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
706 finfo.i.creationTime = finfo.i.modifyTime
707 = cpu_to_le16(0x0000);
708 finfo.i.creationDate = finfo.i.modifyDate
709 = finfo.i.lastAccessDate
710 = cpu_to_le16(0x0C21);
712 finfo.i.entryName[0] = '\0';
715 finfo.ino = 2; /* tradition */
717 server->name_space[finfo.volume] = NW_NS_DOS;
720 root_inode = ncp_iget(sb, &finfo);
723 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
724 sb->s_root = d_alloc_root(root_inode);
732 ncp_lock_server(server);
733 ncp_disconnect(server);
734 ncp_unlock_server(server);
736 ncp_stop_tasks(server);
737 vfree(server->rxbuf);
739 vfree(server->txbuf);
741 vfree(server->packet);
743 #ifdef CONFIG_NCPFS_NLS
744 unload_nls(server->nls_io);
745 unload_nls(server->nls_vol);
747 mutex_destroy(&server->rcv.creq_mutex);
748 mutex_destroy(&server->root_setup_lock);
749 mutex_destroy(&server->mutex);
751 if (server->info_filp)
752 fput(server->info_filp);
754 bdi_destroy(&server->bdi);
756 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
758 * The previously used put_filp(ncp_filp); was bogus, since
759 * it doesn't perform proper unlocking.
763 put_pid(data.wdog_pid);
764 sb->s_fs_info = NULL;
769 static void ncp_put_super(struct super_block *sb)
771 struct ncp_server *server = NCP_SBP(sb);
773 ncp_lock_server(server);
774 ncp_disconnect(server);
775 ncp_unlock_server(server);
777 ncp_stop_tasks(server);
779 #ifdef CONFIG_NCPFS_NLS
780 /* unload the NLS charsets */
781 unload_nls(server->nls_vol);
782 unload_nls(server->nls_io);
783 #endif /* CONFIG_NCPFS_NLS */
784 mutex_destroy(&server->rcv.creq_mutex);
785 mutex_destroy(&server->root_setup_lock);
786 mutex_destroy(&server->mutex);
788 if (server->info_filp)
789 fput(server->info_filp);
790 fput(server->ncp_filp);
791 kill_pid(server->m.wdog_pid, SIGTERM, 1);
792 put_pid(server->m.wdog_pid);
794 bdi_destroy(&server->bdi);
795 kfree(server->priv.data);
796 kfree(server->auth.object_name);
797 vfree(server->rxbuf);
798 vfree(server->txbuf);
799 vfree(server->packet);
800 sb->s_fs_info = NULL;
804 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
808 struct ncp_inode_info* ni;
809 struct ncp_server* s;
810 struct ncp_volume_info vi;
811 struct super_block *sb = dentry->d_sb;
831 if (!s->m.mounted_vol[0]) {
835 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
839 err = ncp_get_directory_info(s, dh, &vi);
840 ncp_dirhandle_free(s, dh);
844 buf->f_type = NCP_SUPER_MAGIC;
845 buf->f_bsize = vi.sectors_per_block * 512;
846 buf->f_blocks = vi.total_blocks;
847 buf->f_bfree = vi.free_blocks;
848 buf->f_bavail = vi.free_blocks;
849 buf->f_files = vi.total_dir_entries;
850 buf->f_ffree = vi.available_dir_entries;
854 /* We cannot say how much disk space is left on a mounted
855 NetWare Server, because free space is distributed over
856 volumes, and the current user might have disk quotas. So
857 free space is not that simple to determine. Our decision
858 here is to err conservatively. */
861 buf->f_type = NCP_SUPER_MAGIC;
862 buf->f_bsize = NCP_BLOCK_SIZE;
870 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
872 struct inode *inode = dentry->d_inode;
875 struct nw_modify_dos_info info;
876 struct ncp_server *server;
880 server = NCP_SERVER(inode);
881 if (!server) /* How this could happen? */
884 /* ageing the dentry to force validation */
885 ncp_age_dentry(server, dentry);
887 result = inode_change_ok(inode, attr);
892 if (((attr->ia_valid & ATTR_UID) &&
893 (attr->ia_uid != server->m.uid)))
896 if (((attr->ia_valid & ATTR_GID) &&
897 (attr->ia_gid != server->m.gid)))
900 if (((attr->ia_valid & ATTR_MODE) &&
902 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
906 memset(&info, 0, sizeof(info));
909 if ((attr->ia_valid & ATTR_MODE) != 0)
911 umode_t newmode = attr->ia_mode;
913 info_mask |= DM_ATTRIBUTES;
915 if (S_ISDIR(inode->i_mode)) {
916 newmode &= server->m.dir_mode;
918 #ifdef CONFIG_NCPFS_EXTRAS
919 if (server->m.flags & NCP_MOUNT_EXTRAS) {
920 /* any non-default execute bit set */
921 if (newmode & ~server->m.file_mode & S_IXUGO)
922 info.attributes |= aSHARED | aSYSTEM;
923 /* read for group/world and not in default file_mode */
924 else if (newmode & ~server->m.file_mode & S_IRUGO)
925 info.attributes |= aSHARED;
928 newmode &= server->m.file_mode;
930 if (newmode & S_IWUGO)
931 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
933 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
935 #ifdef CONFIG_NCPFS_NFS_NS
936 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
937 result = ncp_modify_nfs_info(server,
938 NCP_FINFO(inode)->volNumber,
939 NCP_FINFO(inode)->dirEntNum,
943 info.attributes &= ~(aSHARED | aSYSTEM);
945 /* mark partial success */
946 struct iattr tmpattr;
948 tmpattr.ia_valid = ATTR_MODE;
949 tmpattr.ia_mode = attr->ia_mode;
951 setattr_copy(inode, &tmpattr);
952 mark_inode_dirty(inode);
959 /* Do SIZE before attributes, otherwise mtime together with size does not work...
961 if ((attr->ia_valid & ATTR_SIZE) != 0) {
964 DPRINTK("ncpfs: trying to change size to %ld\n",
967 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
971 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
972 attr->ia_size, 0, "", &written);
974 /* According to ndir, the changes only take effect after
976 ncp_inode_close(inode);
977 result = ncp_make_closed(inode);
981 if (attr->ia_size != i_size_read(inode)) {
982 result = vmtruncate(inode, attr->ia_size);
985 mark_inode_dirty(inode);
988 if ((attr->ia_valid & ATTR_CTIME) != 0) {
989 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
990 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
991 &info.creationTime, &info.creationDate);
993 if ((attr->ia_valid & ATTR_MTIME) != 0) {
994 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
995 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
996 &info.modifyTime, &info.modifyDate);
998 if ((attr->ia_valid & ATTR_ATIME) != 0) {
1000 info_mask |= (DM_LAST_ACCESS_DATE);
1001 ncp_date_unix2dos(attr->ia_atime.tv_sec,
1002 &dummy, &info.lastAccessDate);
1004 if (info_mask != 0) {
1005 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1006 inode, info_mask, &info);
1008 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1009 /* NetWare seems not to allow this. I
1010 do not know why. So, just tell the
1011 user everything went fine. This is
1012 a terrible hack, but I do not know
1013 how to do this correctly. */
1018 #ifdef CONFIG_NCPFS_STRONG
1019 if ((!result) && (info_mask & DM_ATTRIBUTES))
1020 NCP_FINFO(inode)->nwattr = info.attributes;
1026 setattr_copy(inode, attr);
1027 mark_inode_dirty(inode);
1035 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1036 int flags, const char *dev_name, void *data)
1038 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1041 static struct file_system_type ncp_fs_type = {
1042 .owner = THIS_MODULE,
1045 .kill_sb = kill_anon_super,
1046 .fs_flags = FS_BINARY_MOUNTDATA,
1049 static int __init init_ncp_fs(void)
1052 DPRINTK("ncpfs: init_ncp_fs called\n");
1054 err = init_inodecache();
1057 err = register_filesystem(&ncp_fs_type);
1062 destroy_inodecache();
1067 static void __exit exit_ncp_fs(void)
1069 DPRINTK("ncpfs: exit_ncp_fs called\n");
1070 unregister_filesystem(&ncp_fs_type);
1071 destroy_inodecache();
1074 module_init(init_ncp_fs)
1075 module_exit(exit_ncp_fs)
1076 MODULE_LICENSE("GPL");