GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / fs / ncpfs / inode.c
blobfbe233c257983131d3d64cf6972e1b72d4638095
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/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
18 #include <linux/time.h>
19 #include <linux/kernel.h>
20 #include <linux/mm.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>
31 #include <linux/mount.h>
32 #include <linux/seq_file.h>
34 #include <linux/ncp_fs.h>
36 #include <net/sock.h>
38 #include "ncplib_kernel.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 vfsmount *);
51 static struct kmem_cache * ncp_inode_cachep;
53 static struct inode *ncp_alloc_inode(struct super_block *sb)
55 struct ncp_inode_info *ei;
56 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
57 if (!ei)
58 return NULL;
59 return &ei->vfs_inode;
62 static void ncp_destroy_inode(struct inode *inode)
64 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
67 static void init_once(void *foo)
69 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
71 mutex_init(&ei->open_mutex);
72 inode_init_once(&ei->vfs_inode);
75 static int init_inodecache(void)
77 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
78 sizeof(struct ncp_inode_info),
79 0, (SLAB_RECLAIM_ACCOUNT|
80 SLAB_MEM_SPREAD),
81 init_once);
82 if (ncp_inode_cachep == NULL)
83 return -ENOMEM;
84 return 0;
87 static void destroy_inodecache(void)
89 kmem_cache_destroy(ncp_inode_cachep);
92 static int ncp_remount(struct super_block *sb, int *flags, char* data)
94 *flags |= MS_NODIRATIME;
95 return 0;
98 static const struct super_operations ncp_sops =
100 .alloc_inode = ncp_alloc_inode,
101 .destroy_inode = ncp_destroy_inode,
102 .drop_inode = generic_delete_inode,
103 .evict_inode = ncp_evict_inode,
104 .put_super = ncp_put_super,
105 .statfs = ncp_statfs,
106 .remount_fs = ncp_remount,
107 .show_options = ncp_show_options,
111 * Fill in the ncpfs-specific information in the inode.
113 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
115 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
116 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
117 NCP_FINFO(inode)->volNumber = nwinfo->volume;
120 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
122 ncp_update_dirent(inode, nwinfo);
123 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
124 NCP_FINFO(inode)->access = nwinfo->access;
125 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
126 sizeof(nwinfo->file_handle));
127 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
128 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
129 NCP_FINFO(inode)->dirEntNum);
132 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
134 /* NFS namespace mode overrides others if it's set. */
135 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
136 nwi->entryName, nwi->nfs.mode);
137 if (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
159 Object ID ??? */
160 inode->i_size = NCP_BLOCK_SIZE;
161 } else {
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)) {
168 case aHIDDEN:
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;
174 break;
177 /* FALLTHROUGH */
178 case 0:
179 if (server->m.flags & NCP_MOUNT_EXTRAS)
180 inode->i_mode |= S_IRUGO;
181 break;
182 case aSYSTEM:
183 if (server->m.flags & NCP_MOUNT_EXTRAS)
184 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
185 break;
186 /* case aSYSTEM|aHIDDEN: */
187 default:
188 /* reserved combination */
189 break;
192 #endif
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);
222 inode->i_nlink = 1;
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,
237 #endif
240 * Get a new inode.
242 struct inode *
243 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
245 struct inode *inode;
247 if (info == NULL) {
248 printk(KERN_ERR "ncp_iget: info is NULL\n");
249 return NULL;
252 inode = new_inode(sb);
253 if (inode) {
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));
268 #endif
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;
273 #endif
274 } else {
275 make_bad_inode(inode);
277 insert_inode_hash(inode);
278 } else
279 printk(KERN_ERR "ncp_iget: iget failed!\n");
280 return inode;
283 static void
284 ncp_evict_inode(struct inode *inode)
286 truncate_inode_pages(&inode->i_data, 0);
287 end_writeback(inode);
289 if (S_ISDIR(inode->i_mode)) {
290 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
293 if (ncp_make_closed(inode) != 0) {
294 /* We can't do anything but complain. */
295 printk(KERN_ERR "ncp_evict_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 int ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
311 struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
312 unsigned int tmp;
314 if (server->m.uid != 0)
315 seq_printf(seq, ",uid=%u", server->m.uid);
316 if (server->m.gid != 0)
317 seq_printf(seq, ",gid=%u", server->m.gid);
318 if (server->m.mounted_uid != 0)
319 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
320 tmp = server->m.file_mode & S_IALLUGO;
321 if (tmp != NCP_DEFAULT_FILE_MODE)
322 seq_printf(seq, ",mode=0%o", tmp);
323 tmp = server->m.dir_mode & S_IALLUGO;
324 if (tmp != NCP_DEFAULT_DIR_MODE)
325 seq_printf(seq, ",dirmode=0%o", tmp);
326 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
327 tmp = server->m.time_out * 100 / HZ;
328 seq_printf(seq, ",timeout=%u", tmp);
330 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
331 seq_printf(seq, ",retry=%u", server->m.retry_count);
332 if (server->m.flags != 0)
333 seq_printf(seq, ",flags=%lu", server->m.flags);
334 if (server->m.wdog_pid != NULL)
335 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
337 return 0;
340 static const struct ncp_option ncp_opts[] = {
341 { "uid", OPT_INT, 'u' },
342 { "gid", OPT_INT, 'g' },
343 { "owner", OPT_INT, 'o' },
344 { "mode", OPT_INT, 'm' },
345 { "dirmode", OPT_INT, 'd' },
346 { "timeout", OPT_INT, 't' },
347 { "retry", OPT_INT, 'r' },
348 { "flags", OPT_INT, 'f' },
349 { "wdogpid", OPT_INT, 'w' },
350 { "ncpfd", OPT_INT, 'n' },
351 { "infofd", OPT_INT, 'i' }, /* v5 */
352 { "version", OPT_INT, 'v' },
353 { NULL, 0, 0 } };
355 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
356 int optval;
357 char *optarg;
358 unsigned long optint;
359 int version = 0;
360 int ret;
362 data->flags = 0;
363 data->int_flags = 0;
364 data->mounted_uid = 0;
365 data->wdog_pid = NULL;
366 data->ncp_fd = ~0;
367 data->time_out = NCP_DEFAULT_TIME_OUT;
368 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
369 data->uid = 0;
370 data->gid = 0;
371 data->file_mode = NCP_DEFAULT_FILE_MODE;
372 data->dir_mode = NCP_DEFAULT_DIR_MODE;
373 data->info_fd = -1;
374 data->mounted_vol[0] = 0;
376 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
377 ret = optval;
378 if (ret < 0)
379 goto err;
380 switch (optval) {
381 case 'u':
382 data->uid = optint;
383 break;
384 case 'g':
385 data->gid = optint;
386 break;
387 case 'o':
388 data->mounted_uid = optint;
389 break;
390 case 'm':
391 data->file_mode = optint;
392 break;
393 case 'd':
394 data->dir_mode = optint;
395 break;
396 case 't':
397 data->time_out = optint;
398 break;
399 case 'r':
400 data->retry_count = optint;
401 break;
402 case 'f':
403 data->flags = optint;
404 break;
405 case 'w':
406 data->wdog_pid = find_get_pid(optint);
407 break;
408 case 'n':
409 data->ncp_fd = optint;
410 break;
411 case 'i':
412 data->info_fd = optint;
413 break;
414 case 'v':
415 ret = -ECHRNG;
416 if (optint < NCP_MOUNT_VERSION_V4)
417 goto err;
418 if (optint > NCP_MOUNT_VERSION_V5)
419 goto err;
420 version = optint;
421 break;
425 return 0;
426 err:
427 put_pid(data->wdog_pid);
428 data->wdog_pid = NULL;
429 return ret;
432 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
434 struct ncp_mount_data_kernel data;
435 struct ncp_server *server;
436 struct file *ncp_filp;
437 struct inode *root_inode;
438 struct inode *sock_inode;
439 struct socket *sock;
440 int error;
441 int default_bufsize;
442 #ifdef CONFIG_NCPFS_PACKET_SIGNING
443 int options;
444 #endif
445 struct ncp_entry_info finfo;
447 data.wdog_pid = NULL;
448 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
449 if (!server)
450 return -ENOMEM;
451 sb->s_fs_info = server;
453 error = -EFAULT;
454 if (raw_data == NULL)
455 goto out;
456 switch (*(int*)raw_data) {
457 case NCP_MOUNT_VERSION:
459 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
461 data.flags = md->flags;
462 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
463 data.mounted_uid = md->mounted_uid;
464 data.wdog_pid = find_get_pid(md->wdog_pid);
465 data.ncp_fd = md->ncp_fd;
466 data.time_out = md->time_out;
467 data.retry_count = md->retry_count;
468 data.uid = md->uid;
469 data.gid = md->gid;
470 data.file_mode = md->file_mode;
471 data.dir_mode = md->dir_mode;
472 data.info_fd = -1;
473 memcpy(data.mounted_vol, md->mounted_vol,
474 NCP_VOLNAME_LEN+1);
476 break;
477 case NCP_MOUNT_VERSION_V4:
479 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
481 data.flags = md->flags;
482 data.int_flags = 0;
483 data.mounted_uid = md->mounted_uid;
484 data.wdog_pid = find_get_pid(md->wdog_pid);
485 data.ncp_fd = md->ncp_fd;
486 data.time_out = md->time_out;
487 data.retry_count = md->retry_count;
488 data.uid = md->uid;
489 data.gid = md->gid;
490 data.file_mode = md->file_mode;
491 data.dir_mode = md->dir_mode;
492 data.info_fd = -1;
493 data.mounted_vol[0] = 0;
495 break;
496 default:
497 error = -ECHRNG;
498 if (memcmp(raw_data, "vers", 4) == 0) {
499 error = ncp_parse_options(&data, raw_data);
501 if (error)
502 goto out;
503 break;
505 error = -EBADF;
506 ncp_filp = fget(data.ncp_fd);
507 if (!ncp_filp)
508 goto out;
509 error = -ENOTSOCK;
510 sock_inode = ncp_filp->f_path.dentry->d_inode;
511 if (!S_ISSOCK(sock_inode->i_mode))
512 goto out_fput;
513 sock = SOCKET_I(sock_inode);
514 if (!sock)
515 goto out_fput;
517 if (sock->type == SOCK_STREAM)
518 default_bufsize = 0xF000;
519 else
520 default_bufsize = 1024;
522 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
523 sb->s_maxbytes = 0xFFFFFFFFU;
524 sb->s_blocksize = 1024; /* Eh... Is this correct? */
525 sb->s_blocksize_bits = 10;
526 sb->s_magic = NCP_SUPER_MAGIC;
527 sb->s_op = &ncp_sops;
528 sb->s_bdi = &server->bdi;
530 server = NCP_SBP(sb);
531 memset(server, 0, sizeof(*server));
533 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
534 if (error)
535 goto out_bdi;
537 server->ncp_filp = ncp_filp;
538 server->ncp_sock = sock;
540 if (data.info_fd != -1) {
541 struct socket *info_sock;
543 error = -EBADF;
544 server->info_filp = fget(data.info_fd);
545 if (!server->info_filp)
546 goto out_fput;
547 error = -ENOTSOCK;
548 sock_inode = server->info_filp->f_path.dentry->d_inode;
549 if (!S_ISSOCK(sock_inode->i_mode))
550 goto out_fput2;
551 info_sock = SOCKET_I(sock_inode);
552 if (!info_sock)
553 goto out_fput2;
554 error = -EBADFD;
555 if (info_sock->type != SOCK_STREAM)
556 goto out_fput2;
557 server->info_sock = info_sock;
560 /* server->lock = 0; */
561 mutex_init(&server->mutex);
562 server->packet = NULL;
563 /* server->buffer_size = 0; */
564 /* server->conn_status = 0; */
565 /* server->root_dentry = NULL; */
566 /* server->root_setuped = 0; */
567 #ifdef CONFIG_NCPFS_PACKET_SIGNING
568 /* server->sign_wanted = 0; */
569 /* server->sign_active = 0; */
570 #endif
571 server->auth.auth_type = NCP_AUTH_NONE;
572 /* server->auth.object_name_len = 0; */
573 /* server->auth.object_name = NULL; */
574 /* server->auth.object_type = 0; */
575 /* server->priv.len = 0; */
576 /* server->priv.data = NULL; */
578 server->m = data;
579 /* Althought anything producing this is buggy, it happens
580 now because of PATH_MAX changes.. */
581 if (server->m.time_out < 1) {
582 server->m.time_out = 10;
583 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
585 server->m.time_out = server->m.time_out * HZ / 100;
586 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
587 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
589 #ifdef CONFIG_NCPFS_NLS
590 /* load the default NLS charsets */
591 server->nls_vol = load_nls_default();
592 server->nls_io = load_nls_default();
593 #endif /* CONFIG_NCPFS_NLS */
595 server->dentry_ttl = 0; /* no caching */
597 INIT_LIST_HEAD(&server->tx.requests);
598 mutex_init(&server->rcv.creq_mutex);
599 server->tx.creq = NULL;
600 server->rcv.creq = NULL;
601 server->data_ready = sock->sk->sk_data_ready;
602 server->write_space = sock->sk->sk_write_space;
603 server->error_report = sock->sk->sk_error_report;
604 sock->sk->sk_user_data = server;
606 init_timer(&server->timeout_tm);
607 #undef NCP_PACKET_SIZE
608 #define NCP_PACKET_SIZE 131072
609 error = -ENOMEM;
610 server->packet_size = NCP_PACKET_SIZE;
611 server->packet = vmalloc(NCP_PACKET_SIZE);
612 if (server->packet == NULL)
613 goto out_nls;
614 server->txbuf = vmalloc(NCP_PACKET_SIZE);
615 if (server->txbuf == NULL)
616 goto out_packet;
617 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
618 if (server->rxbuf == NULL)
619 goto out_txbuf;
621 sock->sk->sk_data_ready = ncp_tcp_data_ready;
622 sock->sk->sk_error_report = ncp_tcp_error_report;
623 if (sock->type == SOCK_STREAM) {
624 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
625 server->rcv.len = 10;
626 server->rcv.state = 0;
627 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
628 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
629 sock->sk->sk_write_space = ncp_tcp_write_space;
630 } else {
631 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
632 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
633 server->timeout_tm.data = (unsigned long)server;
634 server->timeout_tm.function = ncpdgram_timeout_call;
637 ncp_lock_server(server);
638 error = ncp_connect(server);
639 ncp_unlock_server(server);
640 if (error < 0)
641 goto out_rxbuf;
642 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
644 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
645 #ifdef CONFIG_NCPFS_PACKET_SIGNING
646 if (ncp_negotiate_size_and_options(server, default_bufsize,
647 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
649 if (options != NCP_DEFAULT_OPTIONS)
651 if (ncp_negotiate_size_and_options(server,
652 default_bufsize,
653 options & 2,
654 &(server->buffer_size), &options) != 0)
657 goto out_disconnect;
660 if (options & 2)
661 server->sign_wanted = 1;
663 else
664 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
665 if (ncp_negotiate_buffersize(server, default_bufsize,
666 &(server->buffer_size)) != 0)
667 goto out_disconnect;
668 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
670 memset(&finfo, 0, sizeof(finfo));
671 finfo.i.attributes = aDIR;
672 finfo.i.dataStreamSize = 0; /* ignored */
673 finfo.i.dirEntNum = 0;
674 finfo.i.DosDirNum = 0;
675 #ifdef CONFIG_NCPFS_SMALLDOS
676 finfo.i.NSCreator = NW_NS_DOS;
677 #endif
678 finfo.volume = NCP_NUMBER_OF_VOLUMES;
679 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
680 finfo.i.creationTime = finfo.i.modifyTime
681 = cpu_to_le16(0x0000);
682 finfo.i.creationDate = finfo.i.modifyDate
683 = finfo.i.lastAccessDate
684 = cpu_to_le16(0x0C21);
685 finfo.i.nameLen = 0;
686 finfo.i.entryName[0] = '\0';
688 finfo.opened = 0;
689 finfo.ino = 2; /* tradition */
691 server->name_space[finfo.volume] = NW_NS_DOS;
693 error = -ENOMEM;
694 root_inode = ncp_iget(sb, &finfo);
695 if (!root_inode)
696 goto out_disconnect;
697 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
698 sb->s_root = d_alloc_root(root_inode);
699 if (!sb->s_root)
700 goto out_no_root;
701 sb->s_root->d_op = &ncp_root_dentry_operations;
702 return 0;
704 out_no_root:
705 iput(root_inode);
706 out_disconnect:
707 ncp_lock_server(server);
708 ncp_disconnect(server);
709 ncp_unlock_server(server);
710 out_rxbuf:
711 ncp_stop_tasks(server);
712 vfree(server->rxbuf);
713 out_txbuf:
714 vfree(server->txbuf);
715 out_packet:
716 vfree(server->packet);
717 out_nls:
718 #ifdef CONFIG_NCPFS_NLS
719 unload_nls(server->nls_io);
720 unload_nls(server->nls_vol);
721 #endif
722 out_fput2:
723 if (server->info_filp)
724 fput(server->info_filp);
725 out_fput:
726 bdi_destroy(&server->bdi);
727 out_bdi:
728 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
730 * The previously used put_filp(ncp_filp); was bogus, since
731 * it doesn't perform proper unlocking.
733 fput(ncp_filp);
734 out:
735 put_pid(data.wdog_pid);
736 sb->s_fs_info = NULL;
737 kfree(server);
738 return error;
741 static void ncp_put_super(struct super_block *sb)
743 struct ncp_server *server = NCP_SBP(sb);
745 lock_kernel();
747 ncp_lock_server(server);
748 ncp_disconnect(server);
749 ncp_unlock_server(server);
751 ncp_stop_tasks(server);
753 #ifdef CONFIG_NCPFS_NLS
754 /* unload the NLS charsets */
755 unload_nls(server->nls_vol);
756 unload_nls(server->nls_io);
757 #endif /* CONFIG_NCPFS_NLS */
759 if (server->info_filp)
760 fput(server->info_filp);
761 fput(server->ncp_filp);
762 kill_pid(server->m.wdog_pid, SIGTERM, 1);
763 put_pid(server->m.wdog_pid);
765 bdi_destroy(&server->bdi);
766 kfree(server->priv.data);
767 kfree(server->auth.object_name);
768 vfree(server->rxbuf);
769 vfree(server->txbuf);
770 vfree(server->packet);
771 sb->s_fs_info = NULL;
772 kfree(server);
774 unlock_kernel();
777 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
779 struct dentry* d;
780 struct inode* i;
781 struct ncp_inode_info* ni;
782 struct ncp_server* s;
783 struct ncp_volume_info vi;
784 struct super_block *sb = dentry->d_sb;
785 int err;
786 __u8 dh;
788 d = sb->s_root;
789 if (!d) {
790 goto dflt;
792 i = d->d_inode;
793 if (!i) {
794 goto dflt;
796 ni = NCP_FINFO(i);
797 if (!ni) {
798 goto dflt;
800 s = NCP_SBP(sb);
801 if (!s) {
802 goto dflt;
804 if (!s->m.mounted_vol[0]) {
805 goto dflt;
808 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
809 if (err) {
810 goto dflt;
812 err = ncp_get_directory_info(s, dh, &vi);
813 ncp_dirhandle_free(s, dh);
814 if (err) {
815 goto dflt;
817 buf->f_type = NCP_SUPER_MAGIC;
818 buf->f_bsize = vi.sectors_per_block * 512;
819 buf->f_blocks = vi.total_blocks;
820 buf->f_bfree = vi.free_blocks;
821 buf->f_bavail = vi.free_blocks;
822 buf->f_files = vi.total_dir_entries;
823 buf->f_ffree = vi.available_dir_entries;
824 buf->f_namelen = 12;
825 return 0;
827 /* We cannot say how much disk space is left on a mounted
828 NetWare Server, because free space is distributed over
829 volumes, and the current user might have disk quotas. So
830 free space is not that simple to determine. Our decision
831 here is to err conservatively. */
833 dflt:;
834 buf->f_type = NCP_SUPER_MAGIC;
835 buf->f_bsize = NCP_BLOCK_SIZE;
836 buf->f_blocks = 0;
837 buf->f_bfree = 0;
838 buf->f_bavail = 0;
839 buf->f_namelen = 12;
840 return 0;
843 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
845 struct inode *inode = dentry->d_inode;
846 int result = 0;
847 __le32 info_mask;
848 struct nw_modify_dos_info info;
849 struct ncp_server *server;
851 result = -EIO;
853 lock_kernel();
855 server = NCP_SERVER(inode);
856 if ((!server) || !ncp_conn_valid(server))
857 goto out;
859 /* ageing the dentry to force validation */
860 ncp_age_dentry(server, dentry);
862 result = inode_change_ok(inode, attr);
863 if (result < 0)
864 goto out;
866 result = -EPERM;
867 if (((attr->ia_valid & ATTR_UID) &&
868 (attr->ia_uid != server->m.uid)))
869 goto out;
871 if (((attr->ia_valid & ATTR_GID) &&
872 (attr->ia_gid != server->m.gid)))
873 goto out;
875 if (((attr->ia_valid & ATTR_MODE) &&
876 (attr->ia_mode &
877 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
878 goto out;
880 info_mask = 0;
881 memset(&info, 0, sizeof(info));
883 if ((attr->ia_valid & ATTR_MODE) != 0)
885 umode_t newmode = attr->ia_mode;
887 info_mask |= DM_ATTRIBUTES;
889 if (S_ISDIR(inode->i_mode)) {
890 newmode &= server->m.dir_mode;
891 } else {
892 #ifdef CONFIG_NCPFS_EXTRAS
893 if (server->m.flags & NCP_MOUNT_EXTRAS) {
894 /* any non-default execute bit set */
895 if (newmode & ~server->m.file_mode & S_IXUGO)
896 info.attributes |= aSHARED | aSYSTEM;
897 /* read for group/world and not in default file_mode */
898 else if (newmode & ~server->m.file_mode & S_IRUGO)
899 info.attributes |= aSHARED;
900 } else
901 #endif
902 newmode &= server->m.file_mode;
904 if (newmode & S_IWUGO)
905 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
906 else
907 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
909 #ifdef CONFIG_NCPFS_NFS_NS
910 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
911 result = ncp_modify_nfs_info(server,
912 NCP_FINFO(inode)->volNumber,
913 NCP_FINFO(inode)->dirEntNum,
914 attr->ia_mode, 0);
915 if (result != 0)
916 goto out;
917 info.attributes &= ~(aSHARED | aSYSTEM);
919 /* mark partial success */
920 struct iattr tmpattr;
922 tmpattr.ia_valid = ATTR_MODE;
923 tmpattr.ia_mode = attr->ia_mode;
925 setattr_copy(inode, &tmpattr);
926 mark_inode_dirty(inode);
929 #endif
932 /* Do SIZE before attributes, otherwise mtime together with size does not work...
934 if ((attr->ia_valid & ATTR_SIZE) != 0) {
935 int written;
937 DPRINTK("ncpfs: trying to change size to %ld\n",
938 attr->ia_size);
940 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
941 result = -EACCES;
942 goto out;
944 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
945 attr->ia_size, 0, "", &written);
947 /* According to ndir, the changes only take effect after
948 closing the file */
949 ncp_inode_close(inode);
950 result = ncp_make_closed(inode);
951 if (result)
952 goto out;
954 if (attr->ia_size != i_size_read(inode)) {
955 result = vmtruncate(inode, attr->ia_size);
956 if (result)
957 goto out;
958 mark_inode_dirty(inode);
961 if ((attr->ia_valid & ATTR_CTIME) != 0) {
962 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
963 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
964 &info.creationTime, &info.creationDate);
966 if ((attr->ia_valid & ATTR_MTIME) != 0) {
967 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
968 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
969 &info.modifyTime, &info.modifyDate);
971 if ((attr->ia_valid & ATTR_ATIME) != 0) {
972 __le16 dummy;
973 info_mask |= (DM_LAST_ACCESS_DATE);
974 ncp_date_unix2dos(attr->ia_atime.tv_sec,
975 &dummy, &info.lastAccessDate);
977 if (info_mask != 0) {
978 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
979 inode, info_mask, &info);
980 if (result != 0) {
981 result = -EACCES;
983 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
984 /* NetWare seems not to allow this. I
985 do not know why. So, just tell the
986 user everything went fine. This is
987 a terrible hack, but I do not know
988 how to do this correctly. */
989 result = 0;
990 } else
991 goto out;
993 #ifdef CONFIG_NCPFS_STRONG
994 if ((!result) && (info_mask & DM_ATTRIBUTES))
995 NCP_FINFO(inode)->nwattr = info.attributes;
996 #endif
998 if (result)
999 goto out;
1001 setattr_copy(inode, attr);
1002 mark_inode_dirty(inode);
1004 out:
1005 unlock_kernel();
1006 return result;
1009 static int ncp_get_sb(struct file_system_type *fs_type,
1010 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1012 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
1015 static struct file_system_type ncp_fs_type = {
1016 .owner = THIS_MODULE,
1017 .name = "ncpfs",
1018 .get_sb = ncp_get_sb,
1019 .kill_sb = kill_anon_super,
1020 .fs_flags = FS_BINARY_MOUNTDATA,
1023 static int __init init_ncp_fs(void)
1025 int err;
1026 DPRINTK("ncpfs: init_ncp_fs called\n");
1028 err = init_inodecache();
1029 if (err)
1030 goto out1;
1031 err = register_filesystem(&ncp_fs_type);
1032 if (err)
1033 goto out;
1034 return 0;
1035 out:
1036 destroy_inodecache();
1037 out1:
1038 return err;
1041 static void __exit exit_ncp_fs(void)
1043 DPRINTK("ncpfs: exit_ncp_fs called\n");
1044 unregister_filesystem(&ncp_fs_type);
1045 destroy_inodecache();
1048 module_init(init_ncp_fs)
1049 module_exit(exit_ncp_fs)
1050 MODULE_LICENSE("GPL");