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 if (flags & SLAB_CTOR_CONSTRUCTOR) {
64 mutex_init(&ei->open_mutex);
65 inode_init_once(&ei->vfs_inode);
69 static int init_inodecache(void)
71 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
72 sizeof(struct ncp_inode_info),
73 0, (SLAB_RECLAIM_ACCOUNT|
76 if (ncp_inode_cachep == NULL)
81 static void destroy_inodecache(void)
83 kmem_cache_destroy(ncp_inode_cachep);
86 static int ncp_remount(struct super_block *sb, int *flags, char* data)
88 *flags |= MS_NODIRATIME;
92 static const struct super_operations ncp_sops =
94 .alloc_inode = ncp_alloc_inode,
95 .destroy_inode = ncp_destroy_inode,
96 .drop_inode = generic_delete_inode,
97 .delete_inode = ncp_delete_inode,
98 .put_super = ncp_put_super,
100 .remount_fs = ncp_remount,
103 extern struct dentry_operations ncp_root_dentry_operations;
104 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
105 extern const struct address_space_operations ncp_symlink_aops;
106 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
110 * Fill in the ncpfs-specific information in the inode.
112 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
114 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
115 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
116 NCP_FINFO(inode)->volNumber = nwinfo->volume;
119 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
121 ncp_update_dirent(inode, nwinfo);
122 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
123 NCP_FINFO(inode)->access = nwinfo->access;
124 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
125 sizeof(nwinfo->file_handle));
126 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
127 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
128 NCP_FINFO(inode)->dirEntNum);
131 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
133 /* NFS namespace mode overrides others if it's set. */
134 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
135 nwi->entryName, nwi->nfs.mode);
138 inode->i_mode = nwi->nfs.mode;
141 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
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;
151 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
153 struct nw_info_struct *nwi = &nwinfo->i;
154 struct ncp_server *server = NCP_SERVER(inode);
156 if (nwi->attributes & aDIR) {
157 inode->i_mode = server->m.dir_mode;
158 /* for directories dataStreamSize seems to be some
160 inode->i_size = NCP_BLOCK_SIZE;
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)) {
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;
179 if (server->m.flags & NCP_MOUNT_EXTRAS)
180 inode->i_mode |= S_IRUGO;
183 if (server->m.flags & NCP_MOUNT_EXTRAS)
184 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
186 /* case aSYSTEM|aHIDDEN: */
188 /* reserved combination */
194 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
197 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
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);
205 ncp_update_dates(inode, &nwinfo->i);
206 ncp_update_dirent(inode, nwinfo);
210 * Fill in the inode based on the ncp_entry_info structure.
212 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
214 struct ncp_server *server = NCP_SERVER(inode);
216 NCP_FINFO(inode)->flags = 0;
218 ncp_update_attrs(inode, nwinfo);
220 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
223 inode->i_uid = server->m.uid;
224 inode->i_gid = server->m.gid;
226 ncp_update_dates(inode, &nwinfo->i);
227 ncp_update_inode(inode, nwinfo);
230 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
231 static 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,
243 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
248 printk(KERN_ERR "ncp_iget: info is NULL\n");
252 inode = new_inode(sb);
254 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
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));
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;
275 make_bad_inode(inode);
277 insert_inode_hash(inode);
279 printk(KERN_ERR "ncp_iget: iget failed!\n");
284 ncp_delete_inode(struct inode *inode)
286 truncate_inode_pages(&inode->i_data, 0);
288 if (S_ISDIR(inode->i_mode)) {
289 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
292 if (ncp_make_closed(inode) != 0) {
293 /* We can't do anything but complain. */
294 printk(KERN_ERR "ncp_delete_inode: could not close\n");
299 static void ncp_stop_tasks(struct ncp_server *server) {
300 struct sock* sk = server->ncp_sock->sk;
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();
309 static const struct ncp_option ncp_opts[] = {
310 { "uid", OPT_INT, 'u' },
311 { "gid", OPT_INT, 'g' },
312 { "owner", OPT_INT, 'o' },
313 { "mode", OPT_INT, 'm' },
314 { "dirmode", OPT_INT, 'd' },
315 { "timeout", OPT_INT, 't' },
316 { "retry", OPT_INT, 'r' },
317 { "flags", OPT_INT, 'f' },
318 { "wdogpid", OPT_INT, 'w' },
319 { "ncpfd", OPT_INT, 'n' },
320 { "infofd", OPT_INT, 'i' }, /* v5 */
321 { "version", OPT_INT, 'v' },
324 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
327 unsigned long optint;
333 data->mounted_uid = 0;
334 data->wdog_pid = NULL;
337 data->retry_count = 20;
340 data->file_mode = 0600;
341 data->dir_mode = 0700;
343 data->mounted_vol[0] = 0;
345 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
357 data->mounted_uid = optint;
360 data->file_mode = optint;
363 data->dir_mode = optint;
366 data->time_out = optint;
369 data->retry_count = optint;
372 data->flags = optint;
375 data->wdog_pid = find_get_pid(optint);
378 data->ncp_fd = optint;
381 data->info_fd = optint;
385 if (optint < NCP_MOUNT_VERSION_V4)
387 if (optint > NCP_MOUNT_VERSION_V5)
396 put_pid(data->wdog_pid);
397 data->wdog_pid = NULL;
401 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
403 struct ncp_mount_data_kernel data;
404 struct ncp_server *server;
405 struct file *ncp_filp;
406 struct inode *root_inode;
407 struct inode *sock_inode;
411 #ifdef CONFIG_NCPFS_PACKET_SIGNING
414 struct ncp_entry_info finfo;
416 data.wdog_pid = NULL;
417 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
420 sb->s_fs_info = server;
423 if (raw_data == NULL)
425 switch (*(int*)raw_data) {
426 case NCP_MOUNT_VERSION:
428 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
430 data.flags = md->flags;
431 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
432 data.mounted_uid = md->mounted_uid;
433 data.wdog_pid = find_get_pid(md->wdog_pid);
434 data.ncp_fd = md->ncp_fd;
435 data.time_out = md->time_out;
436 data.retry_count = md->retry_count;
439 data.file_mode = md->file_mode;
440 data.dir_mode = md->dir_mode;
442 memcpy(data.mounted_vol, md->mounted_vol,
446 case NCP_MOUNT_VERSION_V4:
448 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
450 data.flags = md->flags;
452 data.mounted_uid = md->mounted_uid;
453 data.wdog_pid = find_get_pid(md->wdog_pid);
454 data.ncp_fd = md->ncp_fd;
455 data.time_out = md->time_out;
456 data.retry_count = md->retry_count;
459 data.file_mode = md->file_mode;
460 data.dir_mode = md->dir_mode;
462 data.mounted_vol[0] = 0;
467 if (memcmp(raw_data, "vers", 4) == 0) {
468 error = ncp_parse_options(&data, raw_data);
475 ncp_filp = fget(data.ncp_fd);
479 sock_inode = ncp_filp->f_path.dentry->d_inode;
480 if (!S_ISSOCK(sock_inode->i_mode))
482 sock = SOCKET_I(sock_inode);
486 if (sock->type == SOCK_STREAM)
487 default_bufsize = 0xF000;
489 default_bufsize = 1024;
491 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
492 sb->s_maxbytes = 0xFFFFFFFFU;
493 sb->s_blocksize = 1024; /* Eh... Is this correct? */
494 sb->s_blocksize_bits = 10;
495 sb->s_magic = NCP_SUPER_MAGIC;
496 sb->s_op = &ncp_sops;
498 server = NCP_SBP(sb);
499 memset(server, 0, sizeof(*server));
501 server->ncp_filp = ncp_filp;
502 server->ncp_sock = sock;
504 if (data.info_fd != -1) {
505 struct socket *info_sock;
508 server->info_filp = fget(data.info_fd);
509 if (!server->info_filp)
512 sock_inode = server->info_filp->f_path.dentry->d_inode;
513 if (!S_ISSOCK(sock_inode->i_mode))
515 info_sock = SOCKET_I(sock_inode);
519 if (info_sock->type != SOCK_STREAM)
521 server->info_sock = info_sock;
524 /* server->lock = 0; */
525 mutex_init(&server->mutex);
526 server->packet = NULL;
527 /* server->buffer_size = 0; */
528 /* server->conn_status = 0; */
529 /* server->root_dentry = NULL; */
530 /* server->root_setuped = 0; */
531 #ifdef CONFIG_NCPFS_PACKET_SIGNING
532 /* server->sign_wanted = 0; */
533 /* server->sign_active = 0; */
535 server->auth.auth_type = NCP_AUTH_NONE;
536 /* server->auth.object_name_len = 0; */
537 /* server->auth.object_name = NULL; */
538 /* server->auth.object_type = 0; */
539 /* server->priv.len = 0; */
540 /* server->priv.data = NULL; */
543 /* Althought anything producing this is buggy, it happens
544 now because of PATH_MAX changes.. */
545 if (server->m.time_out < 1) {
546 server->m.time_out = 10;
547 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
549 server->m.time_out = server->m.time_out * HZ / 100;
550 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
551 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
553 #ifdef CONFIG_NCPFS_NLS
554 /* load the default NLS charsets */
555 server->nls_vol = load_nls_default();
556 server->nls_io = load_nls_default();
557 #endif /* CONFIG_NCPFS_NLS */
559 server->dentry_ttl = 0; /* no caching */
561 INIT_LIST_HEAD(&server->tx.requests);
562 mutex_init(&server->rcv.creq_mutex);
563 server->tx.creq = NULL;
564 server->rcv.creq = NULL;
565 server->data_ready = sock->sk->sk_data_ready;
566 server->write_space = sock->sk->sk_write_space;
567 server->error_report = sock->sk->sk_error_report;
568 sock->sk->sk_user_data = server;
570 init_timer(&server->timeout_tm);
571 #undef NCP_PACKET_SIZE
572 #define NCP_PACKET_SIZE 131072
574 server->packet_size = NCP_PACKET_SIZE;
575 server->packet = vmalloc(NCP_PACKET_SIZE);
576 if (server->packet == NULL)
578 server->txbuf = vmalloc(NCP_PACKET_SIZE);
579 if (server->txbuf == NULL)
581 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
582 if (server->rxbuf == NULL)
585 sock->sk->sk_data_ready = ncp_tcp_data_ready;
586 sock->sk->sk_error_report = ncp_tcp_error_report;
587 if (sock->type == SOCK_STREAM) {
588 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
589 server->rcv.len = 10;
590 server->rcv.state = 0;
591 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
592 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
593 sock->sk->sk_write_space = ncp_tcp_write_space;
595 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
596 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
597 server->timeout_tm.data = (unsigned long)server;
598 server->timeout_tm.function = ncpdgram_timeout_call;
601 ncp_lock_server(server);
602 error = ncp_connect(server);
603 ncp_unlock_server(server);
606 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
608 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
609 #ifdef CONFIG_NCPFS_PACKET_SIGNING
610 if (ncp_negotiate_size_and_options(server, default_bufsize,
611 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
613 if (options != NCP_DEFAULT_OPTIONS)
615 if (ncp_negotiate_size_and_options(server,
618 &(server->buffer_size), &options) != 0)
625 server->sign_wanted = 1;
628 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
629 if (ncp_negotiate_buffersize(server, default_bufsize,
630 &(server->buffer_size)) != 0)
632 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
634 memset(&finfo, 0, sizeof(finfo));
635 finfo.i.attributes = aDIR;
636 finfo.i.dataStreamSize = 0; /* ignored */
637 finfo.i.dirEntNum = 0;
638 finfo.i.DosDirNum = 0;
639 #ifdef CONFIG_NCPFS_SMALLDOS
640 finfo.i.NSCreator = NW_NS_DOS;
642 finfo.volume = NCP_NUMBER_OF_VOLUMES;
643 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
644 finfo.i.creationTime = finfo.i.modifyTime
645 = cpu_to_le16(0x0000);
646 finfo.i.creationDate = finfo.i.modifyDate
647 = finfo.i.lastAccessDate
648 = cpu_to_le16(0x0C21);
650 finfo.i.entryName[0] = '\0';
653 finfo.ino = 2; /* tradition */
655 server->name_space[finfo.volume] = NW_NS_DOS;
658 root_inode = ncp_iget(sb, &finfo);
661 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
662 sb->s_root = d_alloc_root(root_inode);
665 sb->s_root->d_op = &ncp_root_dentry_operations;
671 ncp_lock_server(server);
672 ncp_disconnect(server);
673 ncp_unlock_server(server);
675 ncp_stop_tasks(server);
676 vfree(server->rxbuf);
678 vfree(server->txbuf);
680 vfree(server->packet);
682 #ifdef CONFIG_NCPFS_NLS
683 unload_nls(server->nls_io);
684 unload_nls(server->nls_vol);
687 if (server->info_filp)
688 fput(server->info_filp);
690 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
692 * The previously used put_filp(ncp_filp); was bogous, since
693 * it doesn't proper unlocking.
697 put_pid(data.wdog_pid);
698 sb->s_fs_info = NULL;
703 static void ncp_put_super(struct super_block *sb)
705 struct ncp_server *server = NCP_SBP(sb);
707 ncp_lock_server(server);
708 ncp_disconnect(server);
709 ncp_unlock_server(server);
711 ncp_stop_tasks(server);
713 #ifdef CONFIG_NCPFS_NLS
714 /* unload the NLS charsets */
717 unload_nls(server->nls_vol);
718 server->nls_vol = NULL;
722 unload_nls(server->nls_io);
723 server->nls_io = NULL;
725 #endif /* CONFIG_NCPFS_NLS */
727 if (server->info_filp)
728 fput(server->info_filp);
729 fput(server->ncp_filp);
730 kill_pid(server->m.wdog_pid, SIGTERM, 1);
731 put_pid(server->m.wdog_pid);
733 kfree(server->priv.data);
734 kfree(server->auth.object_name);
735 vfree(server->rxbuf);
736 vfree(server->txbuf);
737 vfree(server->packet);
738 sb->s_fs_info = NULL;
742 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
746 struct ncp_inode_info* ni;
747 struct ncp_server* s;
748 struct ncp_volume_info vi;
749 struct super_block *sb = dentry->d_sb;
769 if (!s->m.mounted_vol[0]) {
773 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
777 err = ncp_get_directory_info(s, dh, &vi);
778 ncp_dirhandle_free(s, dh);
782 buf->f_type = NCP_SUPER_MAGIC;
783 buf->f_bsize = vi.sectors_per_block * 512;
784 buf->f_blocks = vi.total_blocks;
785 buf->f_bfree = vi.free_blocks;
786 buf->f_bavail = vi.free_blocks;
787 buf->f_files = vi.total_dir_entries;
788 buf->f_ffree = vi.available_dir_entries;
792 /* We cannot say how much disk space is left on a mounted
793 NetWare Server, because free space is distributed over
794 volumes, and the current user might have disk quotas. So
795 free space is not that simple to determine. Our decision
796 here is to err conservatively. */
799 buf->f_type = NCP_SUPER_MAGIC;
800 buf->f_bsize = NCP_BLOCK_SIZE;
808 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
810 struct inode *inode = dentry->d_inode;
813 struct nw_modify_dos_info info;
814 struct ncp_server *server;
820 server = NCP_SERVER(inode);
821 if ((!server) || !ncp_conn_valid(server))
824 /* ageing the dentry to force validation */
825 ncp_age_dentry(server, dentry);
827 result = inode_change_ok(inode, attr);
832 if (((attr->ia_valid & ATTR_UID) &&
833 (attr->ia_uid != server->m.uid)))
836 if (((attr->ia_valid & ATTR_GID) &&
837 (attr->ia_gid != server->m.gid)))
840 if (((attr->ia_valid & ATTR_MODE) &&
842 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
846 memset(&info, 0, sizeof(info));
849 if ((attr->ia_valid & ATTR_MODE) != 0)
851 umode_t newmode = attr->ia_mode;
853 info_mask |= DM_ATTRIBUTES;
855 if (S_ISDIR(inode->i_mode)) {
856 newmode &= server->m.dir_mode;
858 #ifdef CONFIG_NCPFS_EXTRAS
859 if (server->m.flags & NCP_MOUNT_EXTRAS) {
860 /* any non-default execute bit set */
861 if (newmode & ~server->m.file_mode & S_IXUGO)
862 info.attributes |= aSHARED | aSYSTEM;
863 /* read for group/world and not in default file_mode */
864 else if (newmode & ~server->m.file_mode & S_IRUGO)
865 info.attributes |= aSHARED;
868 newmode &= server->m.file_mode;
870 if (newmode & S_IWUGO)
871 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
873 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
875 #ifdef CONFIG_NCPFS_NFS_NS
876 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
877 result = ncp_modify_nfs_info(server,
878 NCP_FINFO(inode)->volNumber,
879 NCP_FINFO(inode)->dirEntNum,
883 info.attributes &= ~(aSHARED | aSYSTEM);
885 /* mark partial success */
886 struct iattr tmpattr;
888 tmpattr.ia_valid = ATTR_MODE;
889 tmpattr.ia_mode = attr->ia_mode;
891 result = inode_setattr(inode, &tmpattr);
900 /* Do SIZE before attributes, otherwise mtime together with size does not work...
902 if ((attr->ia_valid & ATTR_SIZE) != 0) {
905 DPRINTK("ncpfs: trying to change size to %ld\n",
908 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
912 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
913 attr->ia_size, 0, "", &written);
915 /* According to ndir, the changes only take effect after
917 ncp_inode_close(inode);
918 result = ncp_make_closed(inode);
922 struct iattr tmpattr;
924 tmpattr.ia_valid = ATTR_SIZE;
925 tmpattr.ia_size = attr->ia_size;
927 result = inode_setattr(inode, &tmpattr);
932 if ((attr->ia_valid & ATTR_CTIME) != 0) {
933 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
934 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
935 &info.creationTime, &info.creationDate);
937 if ((attr->ia_valid & ATTR_MTIME) != 0) {
938 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
939 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
940 &info.modifyTime, &info.modifyDate);
942 if ((attr->ia_valid & ATTR_ATIME) != 0) {
944 info_mask |= (DM_LAST_ACCESS_DATE);
945 ncp_date_unix2dos(attr->ia_atime.tv_sec,
946 &dummy, &info.lastAccessDate);
948 if (info_mask != 0) {
949 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
950 inode, info_mask, &info);
954 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
955 /* NetWare seems not to allow this. I
956 do not know why. So, just tell the
957 user everything went fine. This is
958 a terrible hack, but I do not know
959 how to do this correctly. */
964 #ifdef CONFIG_NCPFS_STRONG
965 if ((!result) && (info_mask & DM_ATTRIBUTES))
966 NCP_FINFO(inode)->nwattr = info.attributes;
970 result = inode_setattr(inode, attr);
976 static int ncp_get_sb(struct file_system_type *fs_type,
977 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
979 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
982 static struct file_system_type ncp_fs_type = {
983 .owner = THIS_MODULE,
985 .get_sb = ncp_get_sb,
986 .kill_sb = kill_anon_super,
989 static int __init init_ncp_fs(void)
992 DPRINTK("ncpfs: init_module called\n");
994 err = init_inodecache();
997 err = register_filesystem(&ncp_fs_type);
1002 destroy_inodecache();
1007 static void __exit exit_ncp_fs(void)
1009 DPRINTK("ncpfs: cleanup_module called\n");
1010 unregister_filesystem(&ncp_fs_type);
1011 destroy_inodecache();
1014 module_init(init_ncp_fs)
1015 module_exit(exit_ncp_fs)
1016 MODULE_LICENSE("GPL");