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/smp_lock.h>
30 #include <linux/vfs.h>
32 #include <linux/ncp_fs.h>
36 #include "ncplib_kernel.h"
39 static void ncp_delete_inode(struct inode *);
40 static void ncp_put_super(struct super_block *);
41 static int ncp_statfs(struct dentry *, struct kstatfs *);
43 static struct kmem_cache * ncp_inode_cachep;
45 static struct inode *ncp_alloc_inode(struct super_block *sb)
47 struct ncp_inode_info *ei;
48 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
51 return &ei->vfs_inode;
54 static void ncp_destroy_inode(struct inode *inode)
56 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
59 static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
61 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
63 mutex_init(&ei->open_mutex);
64 inode_init_once(&ei->vfs_inode);
67 static int init_inodecache(void)
69 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
70 sizeof(struct ncp_inode_info),
71 0, (SLAB_RECLAIM_ACCOUNT|
74 if (ncp_inode_cachep == NULL)
79 static void destroy_inodecache(void)
81 kmem_cache_destroy(ncp_inode_cachep);
84 static int ncp_remount(struct super_block *sb, int *flags, char* data)
86 *flags |= MS_NODIRATIME;
90 static const struct super_operations ncp_sops =
92 .alloc_inode = ncp_alloc_inode,
93 .destroy_inode = ncp_destroy_inode,
94 .drop_inode = generic_delete_inode,
95 .delete_inode = ncp_delete_inode,
96 .put_super = ncp_put_super,
98 .remount_fs = ncp_remount,
101 extern struct dentry_operations ncp_root_dentry_operations;
102 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
103 extern const struct address_space_operations ncp_symlink_aops;
104 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
108 * Fill in the ncpfs-specific information in the inode.
110 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
112 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
113 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
114 NCP_FINFO(inode)->volNumber = nwinfo->volume;
117 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
119 ncp_update_dirent(inode, nwinfo);
120 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
121 NCP_FINFO(inode)->access = nwinfo->access;
122 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
123 sizeof(nwinfo->file_handle));
124 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
125 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
126 NCP_FINFO(inode)->dirEntNum);
129 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
131 /* NFS namespace mode overrides others if it's set. */
132 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
133 nwi->entryName, nwi->nfs.mode);
136 inode->i_mode = nwi->nfs.mode;
139 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
141 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
142 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
143 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
144 inode->i_atime.tv_nsec = 0;
145 inode->i_mtime.tv_nsec = 0;
146 inode->i_ctime.tv_nsec = 0;
149 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
151 struct nw_info_struct *nwi = &nwinfo->i;
152 struct ncp_server *server = NCP_SERVER(inode);
154 if (nwi->attributes & aDIR) {
155 inode->i_mode = server->m.dir_mode;
156 /* for directories dataStreamSize seems to be some
158 inode->i_size = NCP_BLOCK_SIZE;
160 inode->i_mode = server->m.file_mode;
161 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
162 #ifdef CONFIG_NCPFS_EXTRAS
163 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
164 && (nwi->attributes & aSHARED)) {
165 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
167 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
168 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
169 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
170 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
171 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
177 if (server->m.flags & NCP_MOUNT_EXTRAS)
178 inode->i_mode |= S_IRUGO;
181 if (server->m.flags & NCP_MOUNT_EXTRAS)
182 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
184 /* case aSYSTEM|aHIDDEN: */
186 /* reserved combination */
192 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
195 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
197 NCP_FINFO(inode)->flags = 0;
198 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
199 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
200 ncp_update_attrs(inode, nwinfo);
203 ncp_update_dates(inode, &nwinfo->i);
204 ncp_update_dirent(inode, nwinfo);
208 * Fill in the inode based on the ncp_entry_info structure.
210 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
212 struct ncp_server *server = NCP_SERVER(inode);
214 NCP_FINFO(inode)->flags = 0;
216 ncp_update_attrs(inode, nwinfo);
218 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
221 inode->i_uid = server->m.uid;
222 inode->i_gid = server->m.gid;
224 ncp_update_dates(inode, &nwinfo->i);
225 ncp_update_inode(inode, nwinfo);
228 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
229 static const struct inode_operations ncp_symlink_inode_operations = {
230 .readlink = generic_readlink,
231 .follow_link = page_follow_link_light,
232 .put_link = page_put_link,
233 .setattr = ncp_notify_change,
241 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
246 printk(KERN_ERR "ncp_iget: info is NULL\n");
250 inode = new_inode(sb);
252 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
254 inode->i_ino = info->ino;
255 ncp_set_attr(inode, info);
256 if (S_ISREG(inode->i_mode)) {
257 inode->i_op = &ncp_file_inode_operations;
258 inode->i_fop = &ncp_file_operations;
259 } else if (S_ISDIR(inode->i_mode)) {
260 inode->i_op = &ncp_dir_inode_operations;
261 inode->i_fop = &ncp_dir_operations;
262 #ifdef CONFIG_NCPFS_NFS_NS
263 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
264 init_special_inode(inode, inode->i_mode,
265 new_decode_dev(info->i.nfs.rdev));
267 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
268 } else if (S_ISLNK(inode->i_mode)) {
269 inode->i_op = &ncp_symlink_inode_operations;
270 inode->i_data.a_ops = &ncp_symlink_aops;
273 make_bad_inode(inode);
275 insert_inode_hash(inode);
277 printk(KERN_ERR "ncp_iget: iget failed!\n");
282 ncp_delete_inode(struct inode *inode)
284 truncate_inode_pages(&inode->i_data, 0);
286 if (S_ISDIR(inode->i_mode)) {
287 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
290 if (ncp_make_closed(inode) != 0) {
291 /* We can't do anything but complain. */
292 printk(KERN_ERR "ncp_delete_inode: could not close\n");
297 static void ncp_stop_tasks(struct ncp_server *server) {
298 struct sock* sk = server->ncp_sock->sk;
300 sk->sk_error_report = server->error_report;
301 sk->sk_data_ready = server->data_ready;
302 sk->sk_write_space = server->write_space;
303 del_timer_sync(&server->timeout_tm);
304 flush_scheduled_work();
307 static const struct ncp_option ncp_opts[] = {
308 { "uid", OPT_INT, 'u' },
309 { "gid", OPT_INT, 'g' },
310 { "owner", OPT_INT, 'o' },
311 { "mode", OPT_INT, 'm' },
312 { "dirmode", OPT_INT, 'd' },
313 { "timeout", OPT_INT, 't' },
314 { "retry", OPT_INT, 'r' },
315 { "flags", OPT_INT, 'f' },
316 { "wdogpid", OPT_INT, 'w' },
317 { "ncpfd", OPT_INT, 'n' },
318 { "infofd", OPT_INT, 'i' }, /* v5 */
319 { "version", OPT_INT, 'v' },
322 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
325 unsigned long optint;
331 data->mounted_uid = 0;
332 data->wdog_pid = NULL;
335 data->retry_count = 20;
338 data->file_mode = 0600;
339 data->dir_mode = 0700;
341 data->mounted_vol[0] = 0;
343 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
355 data->mounted_uid = optint;
358 data->file_mode = optint;
361 data->dir_mode = optint;
364 data->time_out = optint;
367 data->retry_count = optint;
370 data->flags = optint;
373 data->wdog_pid = find_get_pid(optint);
376 data->ncp_fd = optint;
379 data->info_fd = optint;
383 if (optint < NCP_MOUNT_VERSION_V4)
385 if (optint > NCP_MOUNT_VERSION_V5)
394 put_pid(data->wdog_pid);
395 data->wdog_pid = NULL;
399 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
401 struct ncp_mount_data_kernel data;
402 struct ncp_server *server;
403 struct file *ncp_filp;
404 struct inode *root_inode;
405 struct inode *sock_inode;
409 #ifdef CONFIG_NCPFS_PACKET_SIGNING
412 struct ncp_entry_info finfo;
414 data.wdog_pid = NULL;
415 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
418 sb->s_fs_info = server;
421 if (raw_data == NULL)
423 switch (*(int*)raw_data) {
424 case NCP_MOUNT_VERSION:
426 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
428 data.flags = md->flags;
429 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
430 data.mounted_uid = md->mounted_uid;
431 data.wdog_pid = find_get_pid(md->wdog_pid);
432 data.ncp_fd = md->ncp_fd;
433 data.time_out = md->time_out;
434 data.retry_count = md->retry_count;
437 data.file_mode = md->file_mode;
438 data.dir_mode = md->dir_mode;
440 memcpy(data.mounted_vol, md->mounted_vol,
444 case NCP_MOUNT_VERSION_V4:
446 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
448 data.flags = md->flags;
450 data.mounted_uid = md->mounted_uid;
451 data.wdog_pid = find_get_pid(md->wdog_pid);
452 data.ncp_fd = md->ncp_fd;
453 data.time_out = md->time_out;
454 data.retry_count = md->retry_count;
457 data.file_mode = md->file_mode;
458 data.dir_mode = md->dir_mode;
460 data.mounted_vol[0] = 0;
465 if (memcmp(raw_data, "vers", 4) == 0) {
466 error = ncp_parse_options(&data, raw_data);
473 ncp_filp = fget(data.ncp_fd);
477 sock_inode = ncp_filp->f_path.dentry->d_inode;
478 if (!S_ISSOCK(sock_inode->i_mode))
480 sock = SOCKET_I(sock_inode);
484 if (sock->type == SOCK_STREAM)
485 default_bufsize = 0xF000;
487 default_bufsize = 1024;
489 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
490 sb->s_maxbytes = 0xFFFFFFFFU;
491 sb->s_blocksize = 1024; /* Eh... Is this correct? */
492 sb->s_blocksize_bits = 10;
493 sb->s_magic = NCP_SUPER_MAGIC;
494 sb->s_op = &ncp_sops;
496 server = NCP_SBP(sb);
497 memset(server, 0, sizeof(*server));
499 server->ncp_filp = ncp_filp;
500 server->ncp_sock = sock;
502 if (data.info_fd != -1) {
503 struct socket *info_sock;
506 server->info_filp = fget(data.info_fd);
507 if (!server->info_filp)
510 sock_inode = server->info_filp->f_path.dentry->d_inode;
511 if (!S_ISSOCK(sock_inode->i_mode))
513 info_sock = SOCKET_I(sock_inode);
517 if (info_sock->type != SOCK_STREAM)
519 server->info_sock = info_sock;
522 /* server->lock = 0; */
523 mutex_init(&server->mutex);
524 server->packet = NULL;
525 /* server->buffer_size = 0; */
526 /* server->conn_status = 0; */
527 /* server->root_dentry = NULL; */
528 /* server->root_setuped = 0; */
529 #ifdef CONFIG_NCPFS_PACKET_SIGNING
530 /* server->sign_wanted = 0; */
531 /* server->sign_active = 0; */
533 server->auth.auth_type = NCP_AUTH_NONE;
534 /* server->auth.object_name_len = 0; */
535 /* server->auth.object_name = NULL; */
536 /* server->auth.object_type = 0; */
537 /* server->priv.len = 0; */
538 /* server->priv.data = NULL; */
541 /* Althought anything producing this is buggy, it happens
542 now because of PATH_MAX changes.. */
543 if (server->m.time_out < 1) {
544 server->m.time_out = 10;
545 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
547 server->m.time_out = server->m.time_out * HZ / 100;
548 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
549 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
551 #ifdef CONFIG_NCPFS_NLS
552 /* load the default NLS charsets */
553 server->nls_vol = load_nls_default();
554 server->nls_io = load_nls_default();
555 #endif /* CONFIG_NCPFS_NLS */
557 server->dentry_ttl = 0; /* no caching */
559 INIT_LIST_HEAD(&server->tx.requests);
560 mutex_init(&server->rcv.creq_mutex);
561 server->tx.creq = NULL;
562 server->rcv.creq = NULL;
563 server->data_ready = sock->sk->sk_data_ready;
564 server->write_space = sock->sk->sk_write_space;
565 server->error_report = sock->sk->sk_error_report;
566 sock->sk->sk_user_data = server;
568 init_timer(&server->timeout_tm);
569 #undef NCP_PACKET_SIZE
570 #define NCP_PACKET_SIZE 131072
572 server->packet_size = NCP_PACKET_SIZE;
573 server->packet = vmalloc(NCP_PACKET_SIZE);
574 if (server->packet == NULL)
576 server->txbuf = vmalloc(NCP_PACKET_SIZE);
577 if (server->txbuf == NULL)
579 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
580 if (server->rxbuf == NULL)
583 sock->sk->sk_data_ready = ncp_tcp_data_ready;
584 sock->sk->sk_error_report = ncp_tcp_error_report;
585 if (sock->type == SOCK_STREAM) {
586 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
587 server->rcv.len = 10;
588 server->rcv.state = 0;
589 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
590 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
591 sock->sk->sk_write_space = ncp_tcp_write_space;
593 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
594 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
595 server->timeout_tm.data = (unsigned long)server;
596 server->timeout_tm.function = ncpdgram_timeout_call;
599 ncp_lock_server(server);
600 error = ncp_connect(server);
601 ncp_unlock_server(server);
604 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
606 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
607 #ifdef CONFIG_NCPFS_PACKET_SIGNING
608 if (ncp_negotiate_size_and_options(server, default_bufsize,
609 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
611 if (options != NCP_DEFAULT_OPTIONS)
613 if (ncp_negotiate_size_and_options(server,
616 &(server->buffer_size), &options) != 0)
623 server->sign_wanted = 1;
626 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
627 if (ncp_negotiate_buffersize(server, default_bufsize,
628 &(server->buffer_size)) != 0)
630 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
632 memset(&finfo, 0, sizeof(finfo));
633 finfo.i.attributes = aDIR;
634 finfo.i.dataStreamSize = 0; /* ignored */
635 finfo.i.dirEntNum = 0;
636 finfo.i.DosDirNum = 0;
637 #ifdef CONFIG_NCPFS_SMALLDOS
638 finfo.i.NSCreator = NW_NS_DOS;
640 finfo.volume = NCP_NUMBER_OF_VOLUMES;
641 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
642 finfo.i.creationTime = finfo.i.modifyTime
643 = cpu_to_le16(0x0000);
644 finfo.i.creationDate = finfo.i.modifyDate
645 = finfo.i.lastAccessDate
646 = cpu_to_le16(0x0C21);
648 finfo.i.entryName[0] = '\0';
651 finfo.ino = 2; /* tradition */
653 server->name_space[finfo.volume] = NW_NS_DOS;
656 root_inode = ncp_iget(sb, &finfo);
659 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
660 sb->s_root = d_alloc_root(root_inode);
663 sb->s_root->d_op = &ncp_root_dentry_operations;
669 ncp_lock_server(server);
670 ncp_disconnect(server);
671 ncp_unlock_server(server);
673 ncp_stop_tasks(server);
674 vfree(server->rxbuf);
676 vfree(server->txbuf);
678 vfree(server->packet);
680 #ifdef CONFIG_NCPFS_NLS
681 unload_nls(server->nls_io);
682 unload_nls(server->nls_vol);
685 if (server->info_filp)
686 fput(server->info_filp);
688 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
690 * The previously used put_filp(ncp_filp); was bogous, since
691 * it doesn't proper unlocking.
695 put_pid(data.wdog_pid);
696 sb->s_fs_info = NULL;
701 static void ncp_put_super(struct super_block *sb)
703 struct ncp_server *server = NCP_SBP(sb);
705 ncp_lock_server(server);
706 ncp_disconnect(server);
707 ncp_unlock_server(server);
709 ncp_stop_tasks(server);
711 #ifdef CONFIG_NCPFS_NLS
712 /* unload the NLS charsets */
715 unload_nls(server->nls_vol);
716 server->nls_vol = NULL;
720 unload_nls(server->nls_io);
721 server->nls_io = NULL;
723 #endif /* CONFIG_NCPFS_NLS */
725 if (server->info_filp)
726 fput(server->info_filp);
727 fput(server->ncp_filp);
728 kill_pid(server->m.wdog_pid, SIGTERM, 1);
729 put_pid(server->m.wdog_pid);
731 kfree(server->priv.data);
732 kfree(server->auth.object_name);
733 vfree(server->rxbuf);
734 vfree(server->txbuf);
735 vfree(server->packet);
736 sb->s_fs_info = NULL;
740 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
744 struct ncp_inode_info* ni;
745 struct ncp_server* s;
746 struct ncp_volume_info vi;
747 struct super_block *sb = dentry->d_sb;
767 if (!s->m.mounted_vol[0]) {
771 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
775 err = ncp_get_directory_info(s, dh, &vi);
776 ncp_dirhandle_free(s, dh);
780 buf->f_type = NCP_SUPER_MAGIC;
781 buf->f_bsize = vi.sectors_per_block * 512;
782 buf->f_blocks = vi.total_blocks;
783 buf->f_bfree = vi.free_blocks;
784 buf->f_bavail = vi.free_blocks;
785 buf->f_files = vi.total_dir_entries;
786 buf->f_ffree = vi.available_dir_entries;
790 /* We cannot say how much disk space is left on a mounted
791 NetWare Server, because free space is distributed over
792 volumes, and the current user might have disk quotas. So
793 free space is not that simple to determine. Our decision
794 here is to err conservatively. */
797 buf->f_type = NCP_SUPER_MAGIC;
798 buf->f_bsize = NCP_BLOCK_SIZE;
806 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
808 struct inode *inode = dentry->d_inode;
811 struct nw_modify_dos_info info;
812 struct ncp_server *server;
818 server = NCP_SERVER(inode);
819 if ((!server) || !ncp_conn_valid(server))
822 /* ageing the dentry to force validation */
823 ncp_age_dentry(server, dentry);
825 result = inode_change_ok(inode, attr);
830 if (((attr->ia_valid & ATTR_UID) &&
831 (attr->ia_uid != server->m.uid)))
834 if (((attr->ia_valid & ATTR_GID) &&
835 (attr->ia_gid != server->m.gid)))
838 if (((attr->ia_valid & ATTR_MODE) &&
840 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
844 memset(&info, 0, sizeof(info));
847 if ((attr->ia_valid & ATTR_MODE) != 0)
849 umode_t newmode = attr->ia_mode;
851 info_mask |= DM_ATTRIBUTES;
853 if (S_ISDIR(inode->i_mode)) {
854 newmode &= server->m.dir_mode;
856 #ifdef CONFIG_NCPFS_EXTRAS
857 if (server->m.flags & NCP_MOUNT_EXTRAS) {
858 /* any non-default execute bit set */
859 if (newmode & ~server->m.file_mode & S_IXUGO)
860 info.attributes |= aSHARED | aSYSTEM;
861 /* read for group/world and not in default file_mode */
862 else if (newmode & ~server->m.file_mode & S_IRUGO)
863 info.attributes |= aSHARED;
866 newmode &= server->m.file_mode;
868 if (newmode & S_IWUGO)
869 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
871 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
873 #ifdef CONFIG_NCPFS_NFS_NS
874 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
875 result = ncp_modify_nfs_info(server,
876 NCP_FINFO(inode)->volNumber,
877 NCP_FINFO(inode)->dirEntNum,
881 info.attributes &= ~(aSHARED | aSYSTEM);
883 /* mark partial success */
884 struct iattr tmpattr;
886 tmpattr.ia_valid = ATTR_MODE;
887 tmpattr.ia_mode = attr->ia_mode;
889 result = inode_setattr(inode, &tmpattr);
898 /* Do SIZE before attributes, otherwise mtime together with size does not work...
900 if ((attr->ia_valid & ATTR_SIZE) != 0) {
903 DPRINTK("ncpfs: trying to change size to %ld\n",
906 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
910 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
911 attr->ia_size, 0, "", &written);
913 /* According to ndir, the changes only take effect after
915 ncp_inode_close(inode);
916 result = ncp_make_closed(inode);
920 struct iattr tmpattr;
922 tmpattr.ia_valid = ATTR_SIZE;
923 tmpattr.ia_size = attr->ia_size;
925 result = inode_setattr(inode, &tmpattr);
930 if ((attr->ia_valid & ATTR_CTIME) != 0) {
931 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
932 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
933 &info.creationTime, &info.creationDate);
935 if ((attr->ia_valid & ATTR_MTIME) != 0) {
936 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
937 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
938 &info.modifyTime, &info.modifyDate);
940 if ((attr->ia_valid & ATTR_ATIME) != 0) {
942 info_mask |= (DM_LAST_ACCESS_DATE);
943 ncp_date_unix2dos(attr->ia_atime.tv_sec,
944 &dummy, &info.lastAccessDate);
946 if (info_mask != 0) {
947 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
948 inode, info_mask, &info);
952 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
953 /* NetWare seems not to allow this. I
954 do not know why. So, just tell the
955 user everything went fine. This is
956 a terrible hack, but I do not know
957 how to do this correctly. */
962 #ifdef CONFIG_NCPFS_STRONG
963 if ((!result) && (info_mask & DM_ATTRIBUTES))
964 NCP_FINFO(inode)->nwattr = info.attributes;
968 result = inode_setattr(inode, attr);
974 static int ncp_get_sb(struct file_system_type *fs_type,
975 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
977 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
980 static struct file_system_type ncp_fs_type = {
981 .owner = THIS_MODULE,
983 .get_sb = ncp_get_sb,
984 .kill_sb = kill_anon_super,
987 static int __init init_ncp_fs(void)
990 DPRINTK("ncpfs: init_module called\n");
992 err = init_inodecache();
995 err = register_filesystem(&ncp_fs_type);
1000 destroy_inodecache();
1005 static void __exit exit_ncp_fs(void)
1007 DPRINTK("ncpfs: cleanup_module called\n");
1008 unregister_filesystem(&ncp_fs_type);
1009 destroy_inodecache();
1012 module_init(init_ncp_fs)
1013 module_exit(exit_ncp_fs)
1014 MODULE_LICENSE("GPL");