Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / staging / ncpfs / inode.c
blobbb411610a0711eaf4362453c670618c946650405
1 /*
2 * inode.c
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/module.h>
16 #include <linux/uaccess.h>
17 #include <asm/byteorder.h>
19 #include <linux/time.h>
20 #include <linux/kernel.h>
21 #include <linux/mm.h>
22 #include <linux/string.h>
23 #include <linux/stat.h>
24 #include <linux/errno.h>
25 #include <linux/file.h>
26 #include <linux/fcntl.h>
27 #include <linux/slab.h>
28 #include <linux/vmalloc.h>
29 #include <linux/init.h>
30 #include <linux/vfs.h>
31 #include <linux/mount.h>
32 #include <linux/seq_file.h>
33 #include <linux/sched/signal.h>
34 #include <linux/namei.h>
36 #include <net/sock.h>
38 #include "ncp_fs.h"
39 #include "getopt.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 dentry *);
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;
57 ei = kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
58 if (!ei)
59 return NULL;
60 return &ei->vfs_inode;
63 static void ncp_i_callback(struct rcu_head *head)
65 struct inode *inode = container_of(head, struct inode, i_rcu);
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|
87 SLAB_MEM_SPREAD|SLAB_ACCOUNT),
88 init_once);
89 if (ncp_inode_cachep == NULL)
90 return -ENOMEM;
91 return 0;
94 static void destroy_inodecache(void)
97 * Make sure all delayed rcu free inodes are flushed before we
98 * destroy cache.
100 rcu_barrier();
101 kmem_cache_destroy(ncp_inode_cachep);
104 static int ncp_remount(struct super_block *sb, int *flags, char* data)
106 sync_filesystem(sb);
107 *flags |= SB_NODIRATIME;
108 return 0;
111 static const struct super_operations ncp_sops =
113 .alloc_inode = ncp_alloc_inode,
114 .destroy_inode = ncp_destroy_inode,
115 .drop_inode = generic_delete_inode,
116 .evict_inode = ncp_evict_inode,
117 .put_super = ncp_put_super,
118 .statfs = ncp_statfs,
119 .remount_fs = ncp_remount,
120 .show_options = ncp_show_options,
124 * Fill in the ncpfs-specific information in the inode.
126 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
128 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
129 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
130 NCP_FINFO(inode)->volNumber = nwinfo->volume;
133 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
135 ncp_update_dirent(inode, nwinfo);
136 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
137 NCP_FINFO(inode)->access = nwinfo->access;
138 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
139 sizeof(nwinfo->file_handle));
140 ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n",
141 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
142 NCP_FINFO(inode)->dirEntNum);
145 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
147 /* NFS namespace mode overrides others if it's set. */
148 ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode);
149 if (nwi->nfs.mode) {
150 /* XXX Security? */
151 inode->i_mode = nwi->nfs.mode;
154 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
156 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
157 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
158 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
159 inode->i_atime.tv_nsec = 0;
160 inode->i_mtime.tv_nsec = 0;
161 inode->i_ctime.tv_nsec = 0;
164 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
166 struct nw_info_struct *nwi = &nwinfo->i;
167 struct ncp_server *server = NCP_SERVER(inode);
169 if (nwi->attributes & aDIR) {
170 inode->i_mode = server->m.dir_mode;
171 /* for directories dataStreamSize seems to be some
172 Object ID ??? */
173 i_size_write(inode, NCP_BLOCK_SIZE);
174 } else {
175 u32 size;
177 inode->i_mode = server->m.file_mode;
178 size = le32_to_cpu(nwi->dataStreamSize);
179 i_size_write(inode, size);
180 #ifdef CONFIG_NCPFS_EXTRAS
181 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
182 && (nwi->attributes & aSHARED)) {
183 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
184 case aHIDDEN:
185 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
186 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
187 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
188 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
189 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
190 break;
193 /* FALLTHROUGH */
194 case 0:
195 if (server->m.flags & NCP_MOUNT_EXTRAS)
196 inode->i_mode |= S_IRUGO;
197 break;
198 case aSYSTEM:
199 if (server->m.flags & NCP_MOUNT_EXTRAS)
200 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
201 break;
202 /* case aSYSTEM|aHIDDEN: */
203 default:
204 /* reserved combination */
205 break;
208 #endif
210 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
213 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
215 NCP_FINFO(inode)->flags = 0;
216 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
217 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
218 ncp_update_attrs(inode, nwinfo);
221 ncp_update_dates(inode, &nwinfo->i);
222 ncp_update_dirent(inode, nwinfo);
226 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
228 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
230 struct ncp_server *server = NCP_SERVER(inode);
232 NCP_FINFO(inode)->flags = 0;
234 ncp_update_attrs(inode, nwinfo);
236 ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode);
238 set_nlink(inode, 1);
239 inode->i_uid = server->m.uid;
240 inode->i_gid = server->m.gid;
242 ncp_update_dates(inode, &nwinfo->i);
243 ncp_update_inode(inode, nwinfo);
246 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
247 static const struct inode_operations ncp_symlink_inode_operations = {
248 .get_link = page_get_link,
249 .setattr = ncp_notify_change,
251 #endif
254 * Get a new inode.
256 struct inode *
257 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
259 struct inode *inode;
261 if (info == NULL) {
262 pr_err("%s: info is NULL\n", __func__);
263 return NULL;
266 inode = new_inode(sb);
267 if (inode) {
268 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
270 inode->i_ino = info->ino;
271 ncp_set_attr(inode, info);
272 if (S_ISREG(inode->i_mode)) {
273 inode->i_op = &ncp_file_inode_operations;
274 inode->i_fop = &ncp_file_operations;
275 } else if (S_ISDIR(inode->i_mode)) {
276 inode->i_op = &ncp_dir_inode_operations;
277 inode->i_fop = &ncp_dir_operations;
278 #ifdef CONFIG_NCPFS_NFS_NS
279 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
280 init_special_inode(inode, inode->i_mode,
281 new_decode_dev(info->i.nfs.rdev));
282 #endif
283 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
284 } else if (S_ISLNK(inode->i_mode)) {
285 inode->i_op = &ncp_symlink_inode_operations;
286 inode_nohighmem(inode);
287 inode->i_data.a_ops = &ncp_symlink_aops;
288 #endif
289 } else {
290 make_bad_inode(inode);
292 insert_inode_hash(inode);
293 } else
294 pr_err("%s: iget failed!\n", __func__);
295 return inode;
298 static void
299 ncp_evict_inode(struct inode *inode)
301 truncate_inode_pages_final(&inode->i_data);
302 clear_inode(inode);
304 if (S_ISDIR(inode->i_mode)) {
305 ncp_dbg(2, "put directory %ld\n", inode->i_ino);
308 if (ncp_make_closed(inode) != 0) {
309 /* We can't do anything but complain. */
310 pr_err("%s: could not close\n", __func__);
314 static void ncp_stop_tasks(struct ncp_server *server) {
315 struct sock* sk = server->ncp_sock->sk;
317 lock_sock(sk);
318 sk->sk_error_report = server->error_report;
319 sk->sk_data_ready = server->data_ready;
320 sk->sk_write_space = server->write_space;
321 release_sock(sk);
322 del_timer_sync(&server->timeout_tm);
324 flush_work(&server->rcv.tq);
325 if (sk->sk_socket->type == SOCK_STREAM)
326 flush_work(&server->tx.tq);
327 else
328 flush_work(&server->timeout_tq);
331 static int ncp_show_options(struct seq_file *seq, struct dentry *root)
333 struct ncp_server *server = NCP_SBP(root->d_sb);
334 unsigned int tmp;
336 if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
337 seq_printf(seq, ",uid=%u",
338 from_kuid_munged(&init_user_ns, server->m.uid));
339 if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
340 seq_printf(seq, ",gid=%u",
341 from_kgid_munged(&init_user_ns, server->m.gid));
342 if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
343 seq_printf(seq, ",owner=%u",
344 from_kuid_munged(&init_user_ns, server->m.mounted_uid));
345 tmp = server->m.file_mode & S_IALLUGO;
346 if (tmp != NCP_DEFAULT_FILE_MODE)
347 seq_printf(seq, ",mode=0%o", tmp);
348 tmp = server->m.dir_mode & S_IALLUGO;
349 if (tmp != NCP_DEFAULT_DIR_MODE)
350 seq_printf(seq, ",dirmode=0%o", tmp);
351 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
352 tmp = server->m.time_out * 100 / HZ;
353 seq_printf(seq, ",timeout=%u", tmp);
355 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
356 seq_printf(seq, ",retry=%u", server->m.retry_count);
357 if (server->m.flags != 0)
358 seq_printf(seq, ",flags=%lu", server->m.flags);
359 if (server->m.wdog_pid != NULL)
360 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
362 return 0;
365 static const struct ncp_option ncp_opts[] = {
366 { "uid", OPT_INT, 'u' },
367 { "gid", OPT_INT, 'g' },
368 { "owner", OPT_INT, 'o' },
369 { "mode", OPT_INT, 'm' },
370 { "dirmode", OPT_INT, 'd' },
371 { "timeout", OPT_INT, 't' },
372 { "retry", OPT_INT, 'r' },
373 { "flags", OPT_INT, 'f' },
374 { "wdogpid", OPT_INT, 'w' },
375 { "ncpfd", OPT_INT, 'n' },
376 { "infofd", OPT_INT, 'i' }, /* v5 */
377 { "version", OPT_INT, 'v' },
378 { NULL, 0, 0 } };
380 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
381 int optval;
382 char *optarg;
383 unsigned long optint;
384 int version = 0;
385 int ret;
387 data->flags = 0;
388 data->int_flags = 0;
389 data->mounted_uid = GLOBAL_ROOT_UID;
390 data->wdog_pid = NULL;
391 data->ncp_fd = ~0;
392 data->time_out = NCP_DEFAULT_TIME_OUT;
393 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
394 data->uid = GLOBAL_ROOT_UID;
395 data->gid = GLOBAL_ROOT_GID;
396 data->file_mode = NCP_DEFAULT_FILE_MODE;
397 data->dir_mode = NCP_DEFAULT_DIR_MODE;
398 data->info_fd = -1;
399 data->mounted_vol[0] = 0;
401 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
402 ret = optval;
403 if (ret < 0)
404 goto err;
405 switch (optval) {
406 case 'u':
407 data->uid = make_kuid(current_user_ns(), optint);
408 if (!uid_valid(data->uid)) {
409 ret = -EINVAL;
410 goto err;
412 break;
413 case 'g':
414 data->gid = make_kgid(current_user_ns(), optint);
415 if (!gid_valid(data->gid)) {
416 ret = -EINVAL;
417 goto err;
419 break;
420 case 'o':
421 data->mounted_uid = make_kuid(current_user_ns(), optint);
422 if (!uid_valid(data->mounted_uid)) {
423 ret = -EINVAL;
424 goto err;
426 break;
427 case 'm':
428 data->file_mode = optint;
429 break;
430 case 'd':
431 data->dir_mode = optint;
432 break;
433 case 't':
434 data->time_out = optint;
435 break;
436 case 'r':
437 data->retry_count = optint;
438 break;
439 case 'f':
440 data->flags = optint;
441 break;
442 case 'w':
443 data->wdog_pid = find_get_pid(optint);
444 break;
445 case 'n':
446 data->ncp_fd = optint;
447 break;
448 case 'i':
449 data->info_fd = optint;
450 break;
451 case 'v':
452 ret = -ECHRNG;
453 if (optint < NCP_MOUNT_VERSION_V4)
454 goto err;
455 if (optint > NCP_MOUNT_VERSION_V5)
456 goto err;
457 version = optint;
458 break;
462 return 0;
463 err:
464 put_pid(data->wdog_pid);
465 data->wdog_pid = NULL;
466 return ret;
469 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
471 struct ncp_mount_data_kernel data;
472 struct ncp_server *server;
473 struct inode *root_inode;
474 struct socket *sock;
475 int error;
476 int default_bufsize;
477 #ifdef CONFIG_NCPFS_PACKET_SIGNING
478 int options;
479 #endif
480 struct ncp_entry_info finfo;
482 memset(&data, 0, sizeof(data));
483 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
484 if (!server)
485 return -ENOMEM;
486 sb->s_fs_info = server;
488 error = -EFAULT;
489 if (raw_data == NULL)
490 goto out;
491 switch (*(int*)raw_data) {
492 case NCP_MOUNT_VERSION:
494 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
496 data.flags = md->flags;
497 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
498 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
499 data.wdog_pid = find_get_pid(md->wdog_pid);
500 data.ncp_fd = md->ncp_fd;
501 data.time_out = md->time_out;
502 data.retry_count = md->retry_count;
503 data.uid = make_kuid(current_user_ns(), md->uid);
504 data.gid = make_kgid(current_user_ns(), md->gid);
505 data.file_mode = md->file_mode;
506 data.dir_mode = md->dir_mode;
507 data.info_fd = -1;
508 memcpy(data.mounted_vol, md->mounted_vol,
509 NCP_VOLNAME_LEN+1);
511 break;
512 case NCP_MOUNT_VERSION_V4:
514 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
516 data.flags = md->flags;
517 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
518 data.wdog_pid = find_get_pid(md->wdog_pid);
519 data.ncp_fd = md->ncp_fd;
520 data.time_out = md->time_out;
521 data.retry_count = md->retry_count;
522 data.uid = make_kuid(current_user_ns(), md->uid);
523 data.gid = make_kgid(current_user_ns(), md->gid);
524 data.file_mode = md->file_mode;
525 data.dir_mode = md->dir_mode;
526 data.info_fd = -1;
528 break;
529 default:
530 error = -ECHRNG;
531 if (memcmp(raw_data, "vers", 4) == 0) {
532 error = ncp_parse_options(&data, raw_data);
534 if (error)
535 goto out;
536 break;
538 error = -EINVAL;
539 if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
540 !gid_valid(data.gid))
541 goto out;
542 sock = sockfd_lookup(data.ncp_fd, &error);
543 if (!sock)
544 goto out;
546 if (sock->type == SOCK_STREAM)
547 default_bufsize = 0xF000;
548 else
549 default_bufsize = 1024;
551 sb->s_flags |= SB_NODIRATIME; /* probably even noatime */
552 sb->s_maxbytes = 0xFFFFFFFFU;
553 sb->s_blocksize = 1024; /* Eh... Is this correct? */
554 sb->s_blocksize_bits = 10;
555 sb->s_magic = NCP_SUPER_MAGIC;
556 sb->s_op = &ncp_sops;
557 sb->s_d_op = &ncp_dentry_operations;
559 server = NCP_SBP(sb);
560 memset(server, 0, sizeof(*server));
562 error = super_setup_bdi(sb);
563 if (error)
564 goto out_fput;
566 server->ncp_sock = sock;
568 if (data.info_fd != -1) {
569 struct socket *info_sock = sockfd_lookup(data.info_fd, &error);
570 if (!info_sock)
571 goto out_fput;
572 server->info_sock = info_sock;
573 error = -EBADFD;
574 if (info_sock->type != SOCK_STREAM)
575 goto out_fput2;
578 /* server->lock = 0; */
579 mutex_init(&server->mutex);
580 server->packet = NULL;
581 /* server->buffer_size = 0; */
582 /* server->conn_status = 0; */
583 /* server->root_dentry = NULL; */
584 /* server->root_setuped = 0; */
585 mutex_init(&server->root_setup_lock);
586 #ifdef CONFIG_NCPFS_PACKET_SIGNING
587 /* server->sign_wanted = 0; */
588 /* server->sign_active = 0; */
589 #endif
590 init_rwsem(&server->auth_rwsem);
591 server->auth.auth_type = NCP_AUTH_NONE;
592 /* server->auth.object_name_len = 0; */
593 /* server->auth.object_name = NULL; */
594 /* server->auth.object_type = 0; */
595 /* server->priv.len = 0; */
596 /* server->priv.data = NULL; */
598 server->m = data;
599 /* Although anything producing this is buggy, it happens
600 now because of PATH_MAX changes.. */
601 if (server->m.time_out < 1) {
602 server->m.time_out = 10;
603 pr_info("You need to recompile your ncpfs utils..\n");
605 server->m.time_out = server->m.time_out * HZ / 100;
606 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
607 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
609 #ifdef CONFIG_NCPFS_NLS
610 /* load the default NLS charsets */
611 server->nls_vol = load_nls_default();
612 server->nls_io = load_nls_default();
613 #endif /* CONFIG_NCPFS_NLS */
615 atomic_set(&server->dentry_ttl, 0); /* no caching */
617 INIT_LIST_HEAD(&server->tx.requests);
618 mutex_init(&server->rcv.creq_mutex);
619 server->tx.creq = NULL;
620 server->rcv.creq = NULL;
622 timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0);
623 #undef NCP_PACKET_SIZE
624 #define NCP_PACKET_SIZE 131072
625 error = -ENOMEM;
626 server->packet_size = NCP_PACKET_SIZE;
627 server->packet = vmalloc(NCP_PACKET_SIZE);
628 if (server->packet == NULL)
629 goto out_nls;
630 server->txbuf = vmalloc(NCP_PACKET_SIZE);
631 if (server->txbuf == NULL)
632 goto out_packet;
633 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
634 if (server->rxbuf == NULL)
635 goto out_txbuf;
637 lock_sock(sock->sk);
638 server->data_ready = sock->sk->sk_data_ready;
639 server->write_space = sock->sk->sk_write_space;
640 server->error_report = sock->sk->sk_error_report;
641 sock->sk->sk_user_data = server;
642 sock->sk->sk_data_ready = ncp_tcp_data_ready;
643 sock->sk->sk_error_report = ncp_tcp_error_report;
644 if (sock->type == SOCK_STREAM) {
645 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
646 server->rcv.len = 10;
647 server->rcv.state = 0;
648 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
649 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
650 sock->sk->sk_write_space = ncp_tcp_write_space;
651 } else {
652 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
653 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
655 release_sock(sock->sk);
657 ncp_lock_server(server);
658 error = ncp_connect(server);
659 ncp_unlock_server(server);
660 if (error < 0)
661 goto out_rxbuf;
662 ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
664 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
665 #ifdef CONFIG_NCPFS_PACKET_SIGNING
666 if (ncp_negotiate_size_and_options(server, default_bufsize,
667 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
669 if (options != NCP_DEFAULT_OPTIONS)
671 if (ncp_negotiate_size_and_options(server,
672 default_bufsize,
673 options & 2,
674 &(server->buffer_size), &options) != 0)
677 goto out_disconnect;
680 ncp_lock_server(server);
681 if (options & 2)
682 server->sign_wanted = 1;
683 ncp_unlock_server(server);
685 else
686 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
687 if (ncp_negotiate_buffersize(server, default_bufsize,
688 &(server->buffer_size)) != 0)
689 goto out_disconnect;
690 ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
692 memset(&finfo, 0, sizeof(finfo));
693 finfo.i.attributes = aDIR;
694 finfo.i.dataStreamSize = 0; /* ignored */
695 finfo.i.dirEntNum = 0;
696 finfo.i.DosDirNum = 0;
697 #ifdef CONFIG_NCPFS_SMALLDOS
698 finfo.i.NSCreator = NW_NS_DOS;
699 #endif
700 finfo.volume = NCP_NUMBER_OF_VOLUMES;
701 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
702 finfo.i.creationTime = finfo.i.modifyTime
703 = cpu_to_le16(0x0000);
704 finfo.i.creationDate = finfo.i.modifyDate
705 = finfo.i.lastAccessDate
706 = cpu_to_le16(0x0C21);
707 finfo.i.nameLen = 0;
708 finfo.i.entryName[0] = '\0';
710 finfo.opened = 0;
711 finfo.ino = 2; /* tradition */
713 server->name_space[finfo.volume] = NW_NS_DOS;
715 error = -ENOMEM;
716 root_inode = ncp_iget(sb, &finfo);
717 if (!root_inode)
718 goto out_disconnect;
719 ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
720 sb->s_root = d_make_root(root_inode);
721 if (!sb->s_root)
722 goto out_disconnect;
723 return 0;
725 out_disconnect:
726 ncp_lock_server(server);
727 ncp_disconnect(server);
728 ncp_unlock_server(server);
729 out_rxbuf:
730 ncp_stop_tasks(server);
731 vfree(server->rxbuf);
732 out_txbuf:
733 vfree(server->txbuf);
734 out_packet:
735 vfree(server->packet);
736 out_nls:
737 #ifdef CONFIG_NCPFS_NLS
738 unload_nls(server->nls_io);
739 unload_nls(server->nls_vol);
740 #endif
741 mutex_destroy(&server->rcv.creq_mutex);
742 mutex_destroy(&server->root_setup_lock);
743 mutex_destroy(&server->mutex);
744 out_fput2:
745 if (server->info_sock)
746 sockfd_put(server->info_sock);
747 out_fput:
748 sockfd_put(sock);
749 out:
750 put_pid(data.wdog_pid);
751 sb->s_fs_info = NULL;
752 kfree(server);
753 return error;
756 static void delayed_free(struct rcu_head *p)
758 struct ncp_server *server = container_of(p, struct ncp_server, rcu);
759 #ifdef CONFIG_NCPFS_NLS
760 /* unload the NLS charsets */
761 unload_nls(server->nls_vol);
762 unload_nls(server->nls_io);
763 #endif /* CONFIG_NCPFS_NLS */
764 kfree(server);
767 static void ncp_put_super(struct super_block *sb)
769 struct ncp_server *server = NCP_SBP(sb);
771 ncp_lock_server(server);
772 ncp_disconnect(server);
773 ncp_unlock_server(server);
775 ncp_stop_tasks(server);
777 mutex_destroy(&server->rcv.creq_mutex);
778 mutex_destroy(&server->root_setup_lock);
779 mutex_destroy(&server->mutex);
781 if (server->info_sock)
782 sockfd_put(server->info_sock);
783 sockfd_put(server->ncp_sock);
784 kill_pid(server->m.wdog_pid, SIGTERM, 1);
785 put_pid(server->m.wdog_pid);
787 kfree(server->priv.data);
788 kfree(server->auth.object_name);
789 vfree(server->rxbuf);
790 vfree(server->txbuf);
791 vfree(server->packet);
792 call_rcu(&server->rcu, delayed_free);
795 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
797 struct dentry* d;
798 struct inode* i;
799 struct ncp_inode_info* ni;
800 struct ncp_server* s;
801 struct ncp_volume_info vi;
802 struct super_block *sb = dentry->d_sb;
803 int err;
804 __u8 dh;
806 d = sb->s_root;
807 if (!d) {
808 goto dflt;
810 i = d_inode(d);
811 if (!i) {
812 goto dflt;
814 ni = NCP_FINFO(i);
815 if (!ni) {
816 goto dflt;
818 s = NCP_SBP(sb);
819 if (!s) {
820 goto dflt;
822 if (!s->m.mounted_vol[0]) {
823 goto dflt;
826 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
827 if (err) {
828 goto dflt;
830 err = ncp_get_directory_info(s, dh, &vi);
831 ncp_dirhandle_free(s, dh);
832 if (err) {
833 goto dflt;
835 buf->f_type = NCP_SUPER_MAGIC;
836 buf->f_bsize = vi.sectors_per_block * 512;
837 buf->f_blocks = vi.total_blocks;
838 buf->f_bfree = vi.free_blocks;
839 buf->f_bavail = vi.free_blocks;
840 buf->f_files = vi.total_dir_entries;
841 buf->f_ffree = vi.available_dir_entries;
842 buf->f_namelen = 12;
843 return 0;
845 /* We cannot say how much disk space is left on a mounted
846 NetWare Server, because free space is distributed over
847 volumes, and the current user might have disk quotas. So
848 free space is not that simple to determine. Our decision
849 here is to err conservatively. */
851 dflt:;
852 buf->f_type = NCP_SUPER_MAGIC;
853 buf->f_bsize = NCP_BLOCK_SIZE;
854 buf->f_blocks = 0;
855 buf->f_bfree = 0;
856 buf->f_bavail = 0;
857 buf->f_namelen = 12;
858 return 0;
861 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
863 struct inode *inode = d_inode(dentry);
864 int result = 0;
865 __le32 info_mask;
866 struct nw_modify_dos_info info;
867 struct ncp_server *server;
869 result = -EIO;
871 server = NCP_SERVER(inode);
872 if (!server) /* How this could happen? */
873 goto out;
875 result = -EPERM;
876 if (IS_DEADDIR(d_inode(dentry)))
877 goto out;
879 /* ageing the dentry to force validation */
880 ncp_age_dentry(server, dentry);
882 result = setattr_prepare(dentry, attr);
883 if (result < 0)
884 goto out;
886 result = -EPERM;
887 if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
888 goto out;
890 if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
891 goto out;
893 if (((attr->ia_valid & ATTR_MODE) &&
894 (attr->ia_mode &
895 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
896 goto out;
898 info_mask = 0;
899 memset(&info, 0, sizeof(info));
901 #if 1
902 if ((attr->ia_valid & ATTR_MODE) != 0)
904 umode_t newmode = attr->ia_mode;
906 info_mask |= DM_ATTRIBUTES;
908 if (S_ISDIR(inode->i_mode)) {
909 newmode &= server->m.dir_mode;
910 } else {
911 #ifdef CONFIG_NCPFS_EXTRAS
912 if (server->m.flags & NCP_MOUNT_EXTRAS) {
913 /* any non-default execute bit set */
914 if (newmode & ~server->m.file_mode & S_IXUGO)
915 info.attributes |= aSHARED | aSYSTEM;
916 /* read for group/world and not in default file_mode */
917 else if (newmode & ~server->m.file_mode & S_IRUGO)
918 info.attributes |= aSHARED;
919 } else
920 #endif
921 newmode &= server->m.file_mode;
923 if (newmode & S_IWUGO)
924 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
925 else
926 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
928 #ifdef CONFIG_NCPFS_NFS_NS
929 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
930 result = ncp_modify_nfs_info(server,
931 NCP_FINFO(inode)->volNumber,
932 NCP_FINFO(inode)->dirEntNum,
933 attr->ia_mode, 0);
934 if (result != 0)
935 goto out;
936 info.attributes &= ~(aSHARED | aSYSTEM);
938 /* mark partial success */
939 struct iattr tmpattr;
941 tmpattr.ia_valid = ATTR_MODE;
942 tmpattr.ia_mode = attr->ia_mode;
944 setattr_copy(inode, &tmpattr);
945 mark_inode_dirty(inode);
948 #endif
950 #endif
952 /* Do SIZE before attributes, otherwise mtime together with size does not work...
954 if ((attr->ia_valid & ATTR_SIZE) != 0) {
955 int written;
957 ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
959 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
960 result = -EACCES;
961 goto out;
963 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
964 attr->ia_size, 0, "", &written);
966 /* According to ndir, the changes only take effect after
967 closing the file */
968 ncp_inode_close(inode);
969 result = ncp_make_closed(inode);
970 if (result)
971 goto out;
973 if (attr->ia_size != i_size_read(inode)) {
974 truncate_setsize(inode, attr->ia_size);
975 mark_inode_dirty(inode);
978 if ((attr->ia_valid & ATTR_CTIME) != 0) {
979 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
980 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
981 &info.creationTime, &info.creationDate);
983 if ((attr->ia_valid & ATTR_MTIME) != 0) {
984 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
985 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
986 &info.modifyTime, &info.modifyDate);
988 if ((attr->ia_valid & ATTR_ATIME) != 0) {
989 __le16 dummy;
990 info_mask |= (DM_LAST_ACCESS_DATE);
991 ncp_date_unix2dos(attr->ia_atime.tv_sec,
992 &dummy, &info.lastAccessDate);
994 if (info_mask != 0) {
995 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
996 inode, info_mask, &info);
997 if (result != 0) {
998 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
999 /* NetWare seems not to allow this. I
1000 do not know why. So, just tell the
1001 user everything went fine. This is
1002 a terrible hack, but I do not know
1003 how to do this correctly. */
1004 result = 0;
1005 } else
1006 goto out;
1008 #ifdef CONFIG_NCPFS_STRONG
1009 if ((!result) && (info_mask & DM_ATTRIBUTES))
1010 NCP_FINFO(inode)->nwattr = info.attributes;
1011 #endif
1013 if (result)
1014 goto out;
1016 setattr_copy(inode, attr);
1017 mark_inode_dirty(inode);
1019 out:
1020 if (result > 0)
1021 result = -EACCES;
1022 return result;
1025 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1026 int flags, const char *dev_name, void *data)
1028 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1031 static struct file_system_type ncp_fs_type = {
1032 .owner = THIS_MODULE,
1033 .name = "ncpfs",
1034 .mount = ncp_mount,
1035 .kill_sb = kill_anon_super,
1036 .fs_flags = FS_BINARY_MOUNTDATA,
1038 MODULE_ALIAS_FS("ncpfs");
1040 static int __init init_ncp_fs(void)
1042 int err;
1043 ncp_dbg(1, "called\n");
1045 err = init_inodecache();
1046 if (err)
1047 goto out1;
1048 err = register_filesystem(&ncp_fs_type);
1049 if (err)
1050 goto out;
1051 return 0;
1052 out:
1053 destroy_inodecache();
1054 out1:
1055 return err;
1058 static void __exit exit_ncp_fs(void)
1060 ncp_dbg(1, "called\n");
1061 unregister_filesystem(&ncp_fs_type);
1062 destroy_inodecache();
1065 module_init(init_ncp_fs)
1066 module_exit(exit_ncp_fs)
1067 MODULE_LICENSE("GPL");