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