mmc_test: fix display of .5 KiB
[linux-2.6/cjktty.git] / fs / ncpfs / inode.c
blob985fabb26aca44edcacc889af0a8d2c5c47e8f04
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 /* XXX Security? */
139 inode->i_mode = nwi->nfs.mode;
142 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
144 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
145 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
146 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
147 inode->i_atime.tv_nsec = 0;
148 inode->i_mtime.tv_nsec = 0;
149 inode->i_ctime.tv_nsec = 0;
152 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
154 struct nw_info_struct *nwi = &nwinfo->i;
155 struct ncp_server *server = NCP_SERVER(inode);
157 if (nwi->attributes & aDIR) {
158 inode->i_mode = server->m.dir_mode;
159 /* for directories dataStreamSize seems to be some
160 Object ID ??? */
161 i_size_write(inode, NCP_BLOCK_SIZE);
162 } else {
163 u32 size;
165 inode->i_mode = server->m.file_mode;
166 size = le32_to_cpu(nwi->dataStreamSize);
167 i_size_write(inode, size);
168 #ifdef CONFIG_NCPFS_EXTRAS
169 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
170 && (nwi->attributes & aSHARED)) {
171 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
172 case aHIDDEN:
173 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
174 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
175 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
176 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
177 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
178 break;
181 /* FALLTHROUGH */
182 case 0:
183 if (server->m.flags & NCP_MOUNT_EXTRAS)
184 inode->i_mode |= S_IRUGO;
185 break;
186 case aSYSTEM:
187 if (server->m.flags & NCP_MOUNT_EXTRAS)
188 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
189 break;
190 /* case aSYSTEM|aHIDDEN: */
191 default:
192 /* reserved combination */
193 break;
196 #endif
198 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
201 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
203 NCP_FINFO(inode)->flags = 0;
204 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
205 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
206 ncp_update_attrs(inode, nwinfo);
209 ncp_update_dates(inode, &nwinfo->i);
210 ncp_update_dirent(inode, nwinfo);
214 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
216 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
218 struct ncp_server *server = NCP_SERVER(inode);
220 NCP_FINFO(inode)->flags = 0;
222 ncp_update_attrs(inode, nwinfo);
224 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
226 inode->i_nlink = 1;
227 inode->i_uid = server->m.uid;
228 inode->i_gid = server->m.gid;
230 ncp_update_dates(inode, &nwinfo->i);
231 ncp_update_inode(inode, nwinfo);
234 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
235 static const struct inode_operations ncp_symlink_inode_operations = {
236 .readlink = generic_readlink,
237 .follow_link = page_follow_link_light,
238 .put_link = page_put_link,
239 .setattr = ncp_notify_change,
241 #endif
244 * Get a new inode.
246 struct inode *
247 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
249 struct inode *inode;
251 if (info == NULL) {
252 printk(KERN_ERR "ncp_iget: info is NULL\n");
253 return NULL;
256 inode = new_inode(sb);
257 if (inode) {
258 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
260 inode->i_mapping->backing_dev_info = sb->s_bdi;
261 inode->i_ino = info->ino;
262 ncp_set_attr(inode, info);
263 if (S_ISREG(inode->i_mode)) {
264 inode->i_op = &ncp_file_inode_operations;
265 inode->i_fop = &ncp_file_operations;
266 } else if (S_ISDIR(inode->i_mode)) {
267 inode->i_op = &ncp_dir_inode_operations;
268 inode->i_fop = &ncp_dir_operations;
269 #ifdef CONFIG_NCPFS_NFS_NS
270 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
271 init_special_inode(inode, inode->i_mode,
272 new_decode_dev(info->i.nfs.rdev));
273 #endif
274 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
275 } else if (S_ISLNK(inode->i_mode)) {
276 inode->i_op = &ncp_symlink_inode_operations;
277 inode->i_data.a_ops = &ncp_symlink_aops;
278 #endif
279 } else {
280 make_bad_inode(inode);
282 insert_inode_hash(inode);
283 } else
284 printk(KERN_ERR "ncp_iget: iget failed!\n");
285 return inode;
288 static void
289 ncp_evict_inode(struct inode *inode)
291 truncate_inode_pages(&inode->i_data, 0);
292 end_writeback(inode);
294 if (S_ISDIR(inode->i_mode)) {
295 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
298 if (ncp_make_closed(inode) != 0) {
299 /* We can't do anything but complain. */
300 printk(KERN_ERR "ncp_evict_inode: could not close\n");
304 static void ncp_stop_tasks(struct ncp_server *server) {
305 struct sock* sk = server->ncp_sock->sk;
307 lock_sock(sk);
308 sk->sk_error_report = server->error_report;
309 sk->sk_data_ready = server->data_ready;
310 sk->sk_write_space = server->write_space;
311 release_sock(sk);
312 del_timer_sync(&server->timeout_tm);
313 flush_scheduled_work();
316 static int ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
318 struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
319 unsigned int tmp;
321 if (server->m.uid != 0)
322 seq_printf(seq, ",uid=%u", server->m.uid);
323 if (server->m.gid != 0)
324 seq_printf(seq, ",gid=%u", server->m.gid);
325 if (server->m.mounted_uid != 0)
326 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
327 tmp = server->m.file_mode & S_IALLUGO;
328 if (tmp != NCP_DEFAULT_FILE_MODE)
329 seq_printf(seq, ",mode=0%o", tmp);
330 tmp = server->m.dir_mode & S_IALLUGO;
331 if (tmp != NCP_DEFAULT_DIR_MODE)
332 seq_printf(seq, ",dirmode=0%o", tmp);
333 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
334 tmp = server->m.time_out * 100 / HZ;
335 seq_printf(seq, ",timeout=%u", tmp);
337 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
338 seq_printf(seq, ",retry=%u", server->m.retry_count);
339 if (server->m.flags != 0)
340 seq_printf(seq, ",flags=%lu", server->m.flags);
341 if (server->m.wdog_pid != NULL)
342 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
344 return 0;
347 static const struct ncp_option ncp_opts[] = {
348 { "uid", OPT_INT, 'u' },
349 { "gid", OPT_INT, 'g' },
350 { "owner", OPT_INT, 'o' },
351 { "mode", OPT_INT, 'm' },
352 { "dirmode", OPT_INT, 'd' },
353 { "timeout", OPT_INT, 't' },
354 { "retry", OPT_INT, 'r' },
355 { "flags", OPT_INT, 'f' },
356 { "wdogpid", OPT_INT, 'w' },
357 { "ncpfd", OPT_INT, 'n' },
358 { "infofd", OPT_INT, 'i' }, /* v5 */
359 { "version", OPT_INT, 'v' },
360 { NULL, 0, 0 } };
362 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
363 int optval;
364 char *optarg;
365 unsigned long optint;
366 int version = 0;
367 int ret;
369 data->flags = 0;
370 data->int_flags = 0;
371 data->mounted_uid = 0;
372 data->wdog_pid = NULL;
373 data->ncp_fd = ~0;
374 data->time_out = NCP_DEFAULT_TIME_OUT;
375 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
376 data->uid = 0;
377 data->gid = 0;
378 data->file_mode = NCP_DEFAULT_FILE_MODE;
379 data->dir_mode = NCP_DEFAULT_DIR_MODE;
380 data->info_fd = -1;
381 data->mounted_vol[0] = 0;
383 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
384 ret = optval;
385 if (ret < 0)
386 goto err;
387 switch (optval) {
388 case 'u':
389 data->uid = optint;
390 break;
391 case 'g':
392 data->gid = optint;
393 break;
394 case 'o':
395 data->mounted_uid = optint;
396 break;
397 case 'm':
398 data->file_mode = optint;
399 break;
400 case 'd':
401 data->dir_mode = optint;
402 break;
403 case 't':
404 data->time_out = optint;
405 break;
406 case 'r':
407 data->retry_count = optint;
408 break;
409 case 'f':
410 data->flags = optint;
411 break;
412 case 'w':
413 data->wdog_pid = find_get_pid(optint);
414 break;
415 case 'n':
416 data->ncp_fd = optint;
417 break;
418 case 'i':
419 data->info_fd = optint;
420 break;
421 case 'v':
422 ret = -ECHRNG;
423 if (optint < NCP_MOUNT_VERSION_V4)
424 goto err;
425 if (optint > NCP_MOUNT_VERSION_V5)
426 goto err;
427 version = optint;
428 break;
432 return 0;
433 err:
434 put_pid(data->wdog_pid);
435 data->wdog_pid = NULL;
436 return ret;
439 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
441 struct ncp_mount_data_kernel data;
442 struct ncp_server *server;
443 struct file *ncp_filp;
444 struct inode *root_inode;
445 struct inode *sock_inode;
446 struct socket *sock;
447 int error;
448 int default_bufsize;
449 #ifdef CONFIG_NCPFS_PACKET_SIGNING
450 int options;
451 #endif
452 struct ncp_entry_info finfo;
454 data.wdog_pid = NULL;
455 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
456 if (!server)
457 return -ENOMEM;
458 sb->s_fs_info = server;
460 error = -EFAULT;
461 if (raw_data == NULL)
462 goto out;
463 switch (*(int*)raw_data) {
464 case NCP_MOUNT_VERSION:
466 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
468 data.flags = md->flags;
469 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
470 data.mounted_uid = md->mounted_uid;
471 data.wdog_pid = find_get_pid(md->wdog_pid);
472 data.ncp_fd = md->ncp_fd;
473 data.time_out = md->time_out;
474 data.retry_count = md->retry_count;
475 data.uid = md->uid;
476 data.gid = md->gid;
477 data.file_mode = md->file_mode;
478 data.dir_mode = md->dir_mode;
479 data.info_fd = -1;
480 memcpy(data.mounted_vol, md->mounted_vol,
481 NCP_VOLNAME_LEN+1);
483 break;
484 case NCP_MOUNT_VERSION_V4:
486 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
488 data.flags = md->flags;
489 data.int_flags = 0;
490 data.mounted_uid = md->mounted_uid;
491 data.wdog_pid = find_get_pid(md->wdog_pid);
492 data.ncp_fd = md->ncp_fd;
493 data.time_out = md->time_out;
494 data.retry_count = md->retry_count;
495 data.uid = md->uid;
496 data.gid = md->gid;
497 data.file_mode = md->file_mode;
498 data.dir_mode = md->dir_mode;
499 data.info_fd = -1;
500 data.mounted_vol[0] = 0;
502 break;
503 default:
504 error = -ECHRNG;
505 if (memcmp(raw_data, "vers", 4) == 0) {
506 error = ncp_parse_options(&data, raw_data);
508 if (error)
509 goto out;
510 break;
512 error = -EBADF;
513 ncp_filp = fget(data.ncp_fd);
514 if (!ncp_filp)
515 goto out;
516 error = -ENOTSOCK;
517 sock_inode = ncp_filp->f_path.dentry->d_inode;
518 if (!S_ISSOCK(sock_inode->i_mode))
519 goto out_fput;
520 sock = SOCKET_I(sock_inode);
521 if (!sock)
522 goto out_fput;
524 if (sock->type == SOCK_STREAM)
525 default_bufsize = 0xF000;
526 else
527 default_bufsize = 1024;
529 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
530 sb->s_maxbytes = 0xFFFFFFFFU;
531 sb->s_blocksize = 1024; /* Eh... Is this correct? */
532 sb->s_blocksize_bits = 10;
533 sb->s_magic = NCP_SUPER_MAGIC;
534 sb->s_op = &ncp_sops;
535 sb->s_bdi = &server->bdi;
537 server = NCP_SBP(sb);
538 memset(server, 0, sizeof(*server));
540 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
541 if (error)
542 goto out_bdi;
544 server->ncp_filp = ncp_filp;
545 server->ncp_sock = sock;
547 if (data.info_fd != -1) {
548 struct socket *info_sock;
550 error = -EBADF;
551 server->info_filp = fget(data.info_fd);
552 if (!server->info_filp)
553 goto out_fput;
554 error = -ENOTSOCK;
555 sock_inode = server->info_filp->f_path.dentry->d_inode;
556 if (!S_ISSOCK(sock_inode->i_mode))
557 goto out_fput2;
558 info_sock = SOCKET_I(sock_inode);
559 if (!info_sock)
560 goto out_fput2;
561 error = -EBADFD;
562 if (info_sock->type != SOCK_STREAM)
563 goto out_fput2;
564 server->info_sock = info_sock;
567 /* server->lock = 0; */
568 mutex_init(&server->mutex);
569 server->packet = NULL;
570 /* server->buffer_size = 0; */
571 /* server->conn_status = 0; */
572 /* server->root_dentry = NULL; */
573 /* server->root_setuped = 0; */
574 mutex_init(&server->root_setup_lock);
575 #ifdef CONFIG_NCPFS_PACKET_SIGNING
576 /* server->sign_wanted = 0; */
577 /* server->sign_active = 0; */
578 #endif
579 init_rwsem(&server->auth_rwsem);
580 server->auth.auth_type = NCP_AUTH_NONE;
581 /* server->auth.object_name_len = 0; */
582 /* server->auth.object_name = NULL; */
583 /* server->auth.object_type = 0; */
584 /* server->priv.len = 0; */
585 /* server->priv.data = NULL; */
587 server->m = data;
588 /* Althought anything producing this is buggy, it happens
589 now because of PATH_MAX changes.. */
590 if (server->m.time_out < 1) {
591 server->m.time_out = 10;
592 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
594 server->m.time_out = server->m.time_out * HZ / 100;
595 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
596 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
598 #ifdef CONFIG_NCPFS_NLS
599 /* load the default NLS charsets */
600 server->nls_vol = load_nls_default();
601 server->nls_io = load_nls_default();
602 #endif /* CONFIG_NCPFS_NLS */
604 atomic_set(&server->dentry_ttl, 0); /* no caching */
606 INIT_LIST_HEAD(&server->tx.requests);
607 mutex_init(&server->rcv.creq_mutex);
608 server->tx.creq = NULL;
609 server->rcv.creq = NULL;
611 init_timer(&server->timeout_tm);
612 #undef NCP_PACKET_SIZE
613 #define NCP_PACKET_SIZE 131072
614 error = -ENOMEM;
615 server->packet_size = NCP_PACKET_SIZE;
616 server->packet = vmalloc(NCP_PACKET_SIZE);
617 if (server->packet == NULL)
618 goto out_nls;
619 server->txbuf = vmalloc(NCP_PACKET_SIZE);
620 if (server->txbuf == NULL)
621 goto out_packet;
622 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
623 if (server->rxbuf == NULL)
624 goto out_txbuf;
626 lock_sock(sock->sk);
627 server->data_ready = sock->sk->sk_data_ready;
628 server->write_space = sock->sk->sk_write_space;
629 server->error_report = sock->sk->sk_error_report;
630 sock->sk->sk_user_data = server;
631 sock->sk->sk_data_ready = ncp_tcp_data_ready;
632 sock->sk->sk_error_report = ncp_tcp_error_report;
633 if (sock->type == SOCK_STREAM) {
634 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
635 server->rcv.len = 10;
636 server->rcv.state = 0;
637 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
638 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
639 sock->sk->sk_write_space = ncp_tcp_write_space;
640 } else {
641 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
642 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
643 server->timeout_tm.data = (unsigned long)server;
644 server->timeout_tm.function = ncpdgram_timeout_call;
646 release_sock(sock->sk);
648 ncp_lock_server(server);
649 error = ncp_connect(server);
650 ncp_unlock_server(server);
651 if (error < 0)
652 goto out_rxbuf;
653 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
655 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
656 #ifdef CONFIG_NCPFS_PACKET_SIGNING
657 if (ncp_negotiate_size_and_options(server, default_bufsize,
658 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
660 if (options != NCP_DEFAULT_OPTIONS)
662 if (ncp_negotiate_size_and_options(server,
663 default_bufsize,
664 options & 2,
665 &(server->buffer_size), &options) != 0)
668 goto out_disconnect;
671 ncp_lock_server(server);
672 if (options & 2)
673 server->sign_wanted = 1;
674 ncp_unlock_server(server);
676 else
677 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
678 if (ncp_negotiate_buffersize(server, default_bufsize,
679 &(server->buffer_size)) != 0)
680 goto out_disconnect;
681 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
683 memset(&finfo, 0, sizeof(finfo));
684 finfo.i.attributes = aDIR;
685 finfo.i.dataStreamSize = 0; /* ignored */
686 finfo.i.dirEntNum = 0;
687 finfo.i.DosDirNum = 0;
688 #ifdef CONFIG_NCPFS_SMALLDOS
689 finfo.i.NSCreator = NW_NS_DOS;
690 #endif
691 finfo.volume = NCP_NUMBER_OF_VOLUMES;
692 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
693 finfo.i.creationTime = finfo.i.modifyTime
694 = cpu_to_le16(0x0000);
695 finfo.i.creationDate = finfo.i.modifyDate
696 = finfo.i.lastAccessDate
697 = cpu_to_le16(0x0C21);
698 finfo.i.nameLen = 0;
699 finfo.i.entryName[0] = '\0';
701 finfo.opened = 0;
702 finfo.ino = 2; /* tradition */
704 server->name_space[finfo.volume] = NW_NS_DOS;
706 error = -ENOMEM;
707 root_inode = ncp_iget(sb, &finfo);
708 if (!root_inode)
709 goto out_disconnect;
710 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
711 sb->s_root = d_alloc_root(root_inode);
712 if (!sb->s_root)
713 goto out_no_root;
714 sb->s_root->d_op = &ncp_root_dentry_operations;
715 return 0;
717 out_no_root:
718 iput(root_inode);
719 out_disconnect:
720 ncp_lock_server(server);
721 ncp_disconnect(server);
722 ncp_unlock_server(server);
723 out_rxbuf:
724 ncp_stop_tasks(server);
725 vfree(server->rxbuf);
726 out_txbuf:
727 vfree(server->txbuf);
728 out_packet:
729 vfree(server->packet);
730 out_nls:
731 #ifdef CONFIG_NCPFS_NLS
732 unload_nls(server->nls_io);
733 unload_nls(server->nls_vol);
734 #endif
735 mutex_destroy(&server->rcv.creq_mutex);
736 mutex_destroy(&server->root_setup_lock);
737 mutex_destroy(&server->mutex);
738 out_fput2:
739 if (server->info_filp)
740 fput(server->info_filp);
741 out_fput:
742 bdi_destroy(&server->bdi);
743 out_bdi:
744 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
746 * The previously used put_filp(ncp_filp); was bogus, since
747 * it doesn't perform proper unlocking.
749 fput(ncp_filp);
750 out:
751 put_pid(data.wdog_pid);
752 sb->s_fs_info = NULL;
753 kfree(server);
754 return error;
757 static void ncp_put_super(struct super_block *sb)
759 struct ncp_server *server = NCP_SBP(sb);
761 ncp_lock_server(server);
762 ncp_disconnect(server);
763 ncp_unlock_server(server);
765 ncp_stop_tasks(server);
767 #ifdef CONFIG_NCPFS_NLS
768 /* unload the NLS charsets */
769 unload_nls(server->nls_vol);
770 unload_nls(server->nls_io);
771 #endif /* CONFIG_NCPFS_NLS */
772 mutex_destroy(&server->rcv.creq_mutex);
773 mutex_destroy(&server->root_setup_lock);
774 mutex_destroy(&server->mutex);
776 if (server->info_filp)
777 fput(server->info_filp);
778 fput(server->ncp_filp);
779 kill_pid(server->m.wdog_pid, SIGTERM, 1);
780 put_pid(server->m.wdog_pid);
782 bdi_destroy(&server->bdi);
783 kfree(server->priv.data);
784 kfree(server->auth.object_name);
785 vfree(server->rxbuf);
786 vfree(server->txbuf);
787 vfree(server->packet);
788 sb->s_fs_info = NULL;
789 kfree(server);
792 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
794 struct dentry* d;
795 struct inode* i;
796 struct ncp_inode_info* ni;
797 struct ncp_server* s;
798 struct ncp_volume_info vi;
799 struct super_block *sb = dentry->d_sb;
800 int err;
801 __u8 dh;
803 d = sb->s_root;
804 if (!d) {
805 goto dflt;
807 i = d->d_inode;
808 if (!i) {
809 goto dflt;
811 ni = NCP_FINFO(i);
812 if (!ni) {
813 goto dflt;
815 s = NCP_SBP(sb);
816 if (!s) {
817 goto dflt;
819 if (!s->m.mounted_vol[0]) {
820 goto dflt;
823 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
824 if (err) {
825 goto dflt;
827 err = ncp_get_directory_info(s, dh, &vi);
828 ncp_dirhandle_free(s, dh);
829 if (err) {
830 goto dflt;
832 buf->f_type = NCP_SUPER_MAGIC;
833 buf->f_bsize = vi.sectors_per_block * 512;
834 buf->f_blocks = vi.total_blocks;
835 buf->f_bfree = vi.free_blocks;
836 buf->f_bavail = vi.free_blocks;
837 buf->f_files = vi.total_dir_entries;
838 buf->f_ffree = vi.available_dir_entries;
839 buf->f_namelen = 12;
840 return 0;
842 /* We cannot say how much disk space is left on a mounted
843 NetWare Server, because free space is distributed over
844 volumes, and the current user might have disk quotas. So
845 free space is not that simple to determine. Our decision
846 here is to err conservatively. */
848 dflt:;
849 buf->f_type = NCP_SUPER_MAGIC;
850 buf->f_bsize = NCP_BLOCK_SIZE;
851 buf->f_blocks = 0;
852 buf->f_bfree = 0;
853 buf->f_bavail = 0;
854 buf->f_namelen = 12;
855 return 0;
858 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
860 struct inode *inode = dentry->d_inode;
861 int result = 0;
862 __le32 info_mask;
863 struct nw_modify_dos_info info;
864 struct ncp_server *server;
866 result = -EIO;
868 server = NCP_SERVER(inode);
869 if (!server) /* How this could happen? */
870 goto out;
872 /* ageing the dentry to force validation */
873 ncp_age_dentry(server, dentry);
875 result = inode_change_ok(inode, attr);
876 if (result < 0)
877 goto out;
879 result = -EPERM;
880 if (((attr->ia_valid & ATTR_UID) &&
881 (attr->ia_uid != server->m.uid)))
882 goto out;
884 if (((attr->ia_valid & ATTR_GID) &&
885 (attr->ia_gid != server->m.gid)))
886 goto out;
888 if (((attr->ia_valid & ATTR_MODE) &&
889 (attr->ia_mode &
890 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
891 goto out;
893 info_mask = 0;
894 memset(&info, 0, sizeof(info));
896 #if 1
897 if ((attr->ia_valid & ATTR_MODE) != 0)
899 umode_t newmode = attr->ia_mode;
901 info_mask |= DM_ATTRIBUTES;
903 if (S_ISDIR(inode->i_mode)) {
904 newmode &= server->m.dir_mode;
905 } else {
906 #ifdef CONFIG_NCPFS_EXTRAS
907 if (server->m.flags & NCP_MOUNT_EXTRAS) {
908 /* any non-default execute bit set */
909 if (newmode & ~server->m.file_mode & S_IXUGO)
910 info.attributes |= aSHARED | aSYSTEM;
911 /* read for group/world and not in default file_mode */
912 else if (newmode & ~server->m.file_mode & S_IRUGO)
913 info.attributes |= aSHARED;
914 } else
915 #endif
916 newmode &= server->m.file_mode;
918 if (newmode & S_IWUGO)
919 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
920 else
921 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
923 #ifdef CONFIG_NCPFS_NFS_NS
924 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
925 result = ncp_modify_nfs_info(server,
926 NCP_FINFO(inode)->volNumber,
927 NCP_FINFO(inode)->dirEntNum,
928 attr->ia_mode, 0);
929 if (result != 0)
930 goto out;
931 info.attributes &= ~(aSHARED | aSYSTEM);
933 /* mark partial success */
934 struct iattr tmpattr;
936 tmpattr.ia_valid = ATTR_MODE;
937 tmpattr.ia_mode = attr->ia_mode;
939 setattr_copy(inode, &tmpattr);
940 mark_inode_dirty(inode);
943 #endif
945 #endif
947 /* Do SIZE before attributes, otherwise mtime together with size does not work...
949 if ((attr->ia_valid & ATTR_SIZE) != 0) {
950 int written;
952 DPRINTK("ncpfs: trying to change size to %ld\n",
953 attr->ia_size);
955 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
956 result = -EACCES;
957 goto out;
959 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
960 attr->ia_size, 0, "", &written);
962 /* According to ndir, the changes only take effect after
963 closing the file */
964 ncp_inode_close(inode);
965 result = ncp_make_closed(inode);
966 if (result)
967 goto out;
969 if (attr->ia_size != i_size_read(inode)) {
970 result = vmtruncate(inode, attr->ia_size);
971 if (result)
972 goto out;
973 mark_inode_dirty(inode);
976 if ((attr->ia_valid & ATTR_CTIME) != 0) {
977 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
978 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
979 &info.creationTime, &info.creationDate);
981 if ((attr->ia_valid & ATTR_MTIME) != 0) {
982 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
983 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
984 &info.modifyTime, &info.modifyDate);
986 if ((attr->ia_valid & ATTR_ATIME) != 0) {
987 __le16 dummy;
988 info_mask |= (DM_LAST_ACCESS_DATE);
989 ncp_date_unix2dos(attr->ia_atime.tv_sec,
990 &dummy, &info.lastAccessDate);
992 if (info_mask != 0) {
993 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
994 inode, info_mask, &info);
995 if (result != 0) {
996 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
997 /* NetWare seems not to allow this. I
998 do not know why. So, just tell the
999 user everything went fine. This is
1000 a terrible hack, but I do not know
1001 how to do this correctly. */
1002 result = 0;
1003 } else
1004 goto out;
1006 #ifdef CONFIG_NCPFS_STRONG
1007 if ((!result) && (info_mask & DM_ATTRIBUTES))
1008 NCP_FINFO(inode)->nwattr = info.attributes;
1009 #endif
1011 if (result)
1012 goto out;
1014 setattr_copy(inode, attr);
1015 mark_inode_dirty(inode);
1017 out:
1018 if (result > 0)
1019 result = -EACCES;
1020 return result;
1023 static int ncp_get_sb(struct file_system_type *fs_type,
1024 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1026 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
1029 static struct file_system_type ncp_fs_type = {
1030 .owner = THIS_MODULE,
1031 .name = "ncpfs",
1032 .get_sb = ncp_get_sb,
1033 .kill_sb = kill_anon_super,
1034 .fs_flags = FS_BINARY_MOUNTDATA,
1037 static int __init init_ncp_fs(void)
1039 int err;
1040 DPRINTK("ncpfs: init_ncp_fs called\n");
1042 err = init_inodecache();
1043 if (err)
1044 goto out1;
1045 err = register_filesystem(&ncp_fs_type);
1046 if (err)
1047 goto out;
1048 return 0;
1049 out:
1050 destroy_inodecache();
1051 out1:
1052 return err;
1055 static void __exit exit_ncp_fs(void)
1057 DPRINTK("ncpfs: exit_ncp_fs called\n");
1058 unregister_filesystem(&ncp_fs_type);
1059 destroy_inodecache();
1062 module_init(init_ncp_fs)
1063 module_exit(exit_ncp_fs)
1064 MODULE_LICENSE("GPL");