drm/i915|intel-gtt: consolidate intel-gtt.h headers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / ncpfs / inode.c
blob8fb93b604e73a3a337a5f43ebc97b25d9f02d7f8
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/vfs.h>
30 #include <linux/mount.h>
31 #include <linux/seq_file.h>
33 #include <linux/ncp_fs.h>
35 #include <net/sock.h>
37 #include "ncplib_kernel.h"
38 #include "getopt.h"
40 #define NCP_DEFAULT_FILE_MODE 0600
41 #define NCP_DEFAULT_DIR_MODE 0700
42 #define NCP_DEFAULT_TIME_OUT 10
43 #define NCP_DEFAULT_RETRY_COUNT 20
45 static void ncp_evict_inode(struct inode *);
46 static void ncp_put_super(struct super_block *);
47 static int ncp_statfs(struct dentry *, struct kstatfs *);
48 static int ncp_show_options(struct seq_file *, struct vfsmount *);
50 static struct kmem_cache * ncp_inode_cachep;
52 static struct inode *ncp_alloc_inode(struct super_block *sb)
54 struct ncp_inode_info *ei;
55 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
56 if (!ei)
57 return NULL;
58 return &ei->vfs_inode;
61 static void ncp_destroy_inode(struct inode *inode)
63 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
66 static void init_once(void *foo)
68 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
70 mutex_init(&ei->open_mutex);
71 inode_init_once(&ei->vfs_inode);
74 static int init_inodecache(void)
76 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
77 sizeof(struct ncp_inode_info),
78 0, (SLAB_RECLAIM_ACCOUNT|
79 SLAB_MEM_SPREAD),
80 init_once);
81 if (ncp_inode_cachep == NULL)
82 return -ENOMEM;
83 return 0;
86 static void destroy_inodecache(void)
88 kmem_cache_destroy(ncp_inode_cachep);
91 static int ncp_remount(struct super_block *sb, int *flags, char* data)
93 *flags |= MS_NODIRATIME;
94 return 0;
97 static const struct super_operations ncp_sops =
99 .alloc_inode = ncp_alloc_inode,
100 .destroy_inode = ncp_destroy_inode,
101 .drop_inode = generic_delete_inode,
102 .evict_inode = ncp_evict_inode,
103 .put_super = ncp_put_super,
104 .statfs = ncp_statfs,
105 .remount_fs = ncp_remount,
106 .show_options = ncp_show_options,
110 * Fill in the ncpfs-specific information in the inode.
112 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
114 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
115 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
116 NCP_FINFO(inode)->volNumber = nwinfo->volume;
119 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
121 ncp_update_dirent(inode, nwinfo);
122 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
123 NCP_FINFO(inode)->access = nwinfo->access;
124 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
125 sizeof(nwinfo->file_handle));
126 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
127 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
128 NCP_FINFO(inode)->dirEntNum);
131 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
133 /* NFS namespace mode overrides others if it's set. */
134 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
135 nwi->entryName, nwi->nfs.mode);
136 if (nwi->nfs.mode) {
137 /* XXX Security? */
138 inode->i_mode = nwi->nfs.mode;
141 inode->i_blocks = (i_size_read(inode) + 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 i_size_write(inode, NCP_BLOCK_SIZE);
161 } else {
162 u32 size;
164 inode->i_mode = server->m.file_mode;
165 size = le32_to_cpu(nwi->dataStreamSize);
166 i_size_write(inode, size);
167 #ifdef CONFIG_NCPFS_EXTRAS
168 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
169 && (nwi->attributes & aSHARED)) {
170 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
171 case aHIDDEN:
172 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
173 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
174 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
175 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
176 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
177 break;
180 /* FALLTHROUGH */
181 case 0:
182 if (server->m.flags & NCP_MOUNT_EXTRAS)
183 inode->i_mode |= S_IRUGO;
184 break;
185 case aSYSTEM:
186 if (server->m.flags & NCP_MOUNT_EXTRAS)
187 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
188 break;
189 /* case aSYSTEM|aHIDDEN: */
190 default:
191 /* reserved combination */
192 break;
195 #endif
197 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
200 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
202 NCP_FINFO(inode)->flags = 0;
203 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
204 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
205 ncp_update_attrs(inode, nwinfo);
208 ncp_update_dates(inode, &nwinfo->i);
209 ncp_update_dirent(inode, nwinfo);
213 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
215 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
217 struct ncp_server *server = NCP_SERVER(inode);
219 NCP_FINFO(inode)->flags = 0;
221 ncp_update_attrs(inode, nwinfo);
223 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
225 inode->i_nlink = 1;
226 inode->i_uid = server->m.uid;
227 inode->i_gid = server->m.gid;
229 ncp_update_dates(inode, &nwinfo->i);
230 ncp_update_inode(inode, nwinfo);
233 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
234 static const struct inode_operations ncp_symlink_inode_operations = {
235 .readlink = generic_readlink,
236 .follow_link = page_follow_link_light,
237 .put_link = page_put_link,
238 .setattr = ncp_notify_change,
240 #endif
243 * Get a new inode.
245 struct inode *
246 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
248 struct inode *inode;
250 if (info == NULL) {
251 printk(KERN_ERR "ncp_iget: info is NULL\n");
252 return NULL;
255 inode = new_inode(sb);
256 if (inode) {
257 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
259 inode->i_mapping->backing_dev_info = sb->s_bdi;
260 inode->i_ino = info->ino;
261 ncp_set_attr(inode, info);
262 if (S_ISREG(inode->i_mode)) {
263 inode->i_op = &ncp_file_inode_operations;
264 inode->i_fop = &ncp_file_operations;
265 } else if (S_ISDIR(inode->i_mode)) {
266 inode->i_op = &ncp_dir_inode_operations;
267 inode->i_fop = &ncp_dir_operations;
268 #ifdef CONFIG_NCPFS_NFS_NS
269 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
270 init_special_inode(inode, inode->i_mode,
271 new_decode_dev(info->i.nfs.rdev));
272 #endif
273 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
274 } else if (S_ISLNK(inode->i_mode)) {
275 inode->i_op = &ncp_symlink_inode_operations;
276 inode->i_data.a_ops = &ncp_symlink_aops;
277 #endif
278 } else {
279 make_bad_inode(inode);
281 insert_inode_hash(inode);
282 } else
283 printk(KERN_ERR "ncp_iget: iget failed!\n");
284 return inode;
287 static void
288 ncp_evict_inode(struct inode *inode)
290 truncate_inode_pages(&inode->i_data, 0);
291 end_writeback(inode);
293 if (S_ISDIR(inode->i_mode)) {
294 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
297 if (ncp_make_closed(inode) != 0) {
298 /* We can't do anything but complain. */
299 printk(KERN_ERR "ncp_evict_inode: could not close\n");
303 static void ncp_stop_tasks(struct ncp_server *server) {
304 struct sock* sk = server->ncp_sock->sk;
306 lock_sock(sk);
307 sk->sk_error_report = server->error_report;
308 sk->sk_data_ready = server->data_ready;
309 sk->sk_write_space = server->write_space;
310 release_sock(sk);
311 del_timer_sync(&server->timeout_tm);
312 flush_scheduled_work();
315 static int ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
317 struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
318 unsigned int tmp;
320 if (server->m.uid != 0)
321 seq_printf(seq, ",uid=%u", server->m.uid);
322 if (server->m.gid != 0)
323 seq_printf(seq, ",gid=%u", server->m.gid);
324 if (server->m.mounted_uid != 0)
325 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
326 tmp = server->m.file_mode & S_IALLUGO;
327 if (tmp != NCP_DEFAULT_FILE_MODE)
328 seq_printf(seq, ",mode=0%o", tmp);
329 tmp = server->m.dir_mode & S_IALLUGO;
330 if (tmp != NCP_DEFAULT_DIR_MODE)
331 seq_printf(seq, ",dirmode=0%o", tmp);
332 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
333 tmp = server->m.time_out * 100 / HZ;
334 seq_printf(seq, ",timeout=%u", tmp);
336 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
337 seq_printf(seq, ",retry=%u", server->m.retry_count);
338 if (server->m.flags != 0)
339 seq_printf(seq, ",flags=%lu", server->m.flags);
340 if (server->m.wdog_pid != NULL)
341 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
343 return 0;
346 static const struct ncp_option ncp_opts[] = {
347 { "uid", OPT_INT, 'u' },
348 { "gid", OPT_INT, 'g' },
349 { "owner", OPT_INT, 'o' },
350 { "mode", OPT_INT, 'm' },
351 { "dirmode", OPT_INT, 'd' },
352 { "timeout", OPT_INT, 't' },
353 { "retry", OPT_INT, 'r' },
354 { "flags", OPT_INT, 'f' },
355 { "wdogpid", OPT_INT, 'w' },
356 { "ncpfd", OPT_INT, 'n' },
357 { "infofd", OPT_INT, 'i' }, /* v5 */
358 { "version", OPT_INT, 'v' },
359 { NULL, 0, 0 } };
361 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
362 int optval;
363 char *optarg;
364 unsigned long optint;
365 int version = 0;
366 int ret;
368 data->flags = 0;
369 data->int_flags = 0;
370 data->mounted_uid = 0;
371 data->wdog_pid = NULL;
372 data->ncp_fd = ~0;
373 data->time_out = NCP_DEFAULT_TIME_OUT;
374 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
375 data->uid = 0;
376 data->gid = 0;
377 data->file_mode = NCP_DEFAULT_FILE_MODE;
378 data->dir_mode = NCP_DEFAULT_DIR_MODE;
379 data->info_fd = -1;
380 data->mounted_vol[0] = 0;
382 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
383 ret = optval;
384 if (ret < 0)
385 goto err;
386 switch (optval) {
387 case 'u':
388 data->uid = optint;
389 break;
390 case 'g':
391 data->gid = optint;
392 break;
393 case 'o':
394 data->mounted_uid = optint;
395 break;
396 case 'm':
397 data->file_mode = optint;
398 break;
399 case 'd':
400 data->dir_mode = optint;
401 break;
402 case 't':
403 data->time_out = optint;
404 break;
405 case 'r':
406 data->retry_count = optint;
407 break;
408 case 'f':
409 data->flags = optint;
410 break;
411 case 'w':
412 data->wdog_pid = find_get_pid(optint);
413 break;
414 case 'n':
415 data->ncp_fd = optint;
416 break;
417 case 'i':
418 data->info_fd = optint;
419 break;
420 case 'v':
421 ret = -ECHRNG;
422 if (optint < NCP_MOUNT_VERSION_V4)
423 goto err;
424 if (optint > NCP_MOUNT_VERSION_V5)
425 goto err;
426 version = optint;
427 break;
431 return 0;
432 err:
433 put_pid(data->wdog_pid);
434 data->wdog_pid = NULL;
435 return ret;
438 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
440 struct ncp_mount_data_kernel data;
441 struct ncp_server *server;
442 struct file *ncp_filp;
443 struct inode *root_inode;
444 struct inode *sock_inode;
445 struct socket *sock;
446 int error;
447 int default_bufsize;
448 #ifdef CONFIG_NCPFS_PACKET_SIGNING
449 int options;
450 #endif
451 struct ncp_entry_info finfo;
453 data.wdog_pid = NULL;
454 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
455 if (!server)
456 return -ENOMEM;
457 sb->s_fs_info = server;
459 error = -EFAULT;
460 if (raw_data == NULL)
461 goto out;
462 switch (*(int*)raw_data) {
463 case NCP_MOUNT_VERSION:
465 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
467 data.flags = md->flags;
468 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
469 data.mounted_uid = md->mounted_uid;
470 data.wdog_pid = find_get_pid(md->wdog_pid);
471 data.ncp_fd = md->ncp_fd;
472 data.time_out = md->time_out;
473 data.retry_count = md->retry_count;
474 data.uid = md->uid;
475 data.gid = md->gid;
476 data.file_mode = md->file_mode;
477 data.dir_mode = md->dir_mode;
478 data.info_fd = -1;
479 memcpy(data.mounted_vol, md->mounted_vol,
480 NCP_VOLNAME_LEN+1);
482 break;
483 case NCP_MOUNT_VERSION_V4:
485 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
487 data.flags = md->flags;
488 data.int_flags = 0;
489 data.mounted_uid = md->mounted_uid;
490 data.wdog_pid = find_get_pid(md->wdog_pid);
491 data.ncp_fd = md->ncp_fd;
492 data.time_out = md->time_out;
493 data.retry_count = md->retry_count;
494 data.uid = md->uid;
495 data.gid = md->gid;
496 data.file_mode = md->file_mode;
497 data.dir_mode = md->dir_mode;
498 data.info_fd = -1;
499 data.mounted_vol[0] = 0;
501 break;
502 default:
503 error = -ECHRNG;
504 if (memcmp(raw_data, "vers", 4) == 0) {
505 error = ncp_parse_options(&data, raw_data);
507 if (error)
508 goto out;
509 break;
511 error = -EBADF;
512 ncp_filp = fget(data.ncp_fd);
513 if (!ncp_filp)
514 goto out;
515 error = -ENOTSOCK;
516 sock_inode = ncp_filp->f_path.dentry->d_inode;
517 if (!S_ISSOCK(sock_inode->i_mode))
518 goto out_fput;
519 sock = SOCKET_I(sock_inode);
520 if (!sock)
521 goto out_fput;
523 if (sock->type == SOCK_STREAM)
524 default_bufsize = 0xF000;
525 else
526 default_bufsize = 1024;
528 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
529 sb->s_maxbytes = 0xFFFFFFFFU;
530 sb->s_blocksize = 1024; /* Eh... Is this correct? */
531 sb->s_blocksize_bits = 10;
532 sb->s_magic = NCP_SUPER_MAGIC;
533 sb->s_op = &ncp_sops;
534 sb->s_bdi = &server->bdi;
536 server = NCP_SBP(sb);
537 memset(server, 0, sizeof(*server));
539 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
540 if (error)
541 goto out_bdi;
543 server->ncp_filp = ncp_filp;
544 server->ncp_sock = sock;
546 if (data.info_fd != -1) {
547 struct socket *info_sock;
549 error = -EBADF;
550 server->info_filp = fget(data.info_fd);
551 if (!server->info_filp)
552 goto out_fput;
553 error = -ENOTSOCK;
554 sock_inode = server->info_filp->f_path.dentry->d_inode;
555 if (!S_ISSOCK(sock_inode->i_mode))
556 goto out_fput2;
557 info_sock = SOCKET_I(sock_inode);
558 if (!info_sock)
559 goto out_fput2;
560 error = -EBADFD;
561 if (info_sock->type != SOCK_STREAM)
562 goto out_fput2;
563 server->info_sock = info_sock;
566 /* server->lock = 0; */
567 mutex_init(&server->mutex);
568 server->packet = NULL;
569 /* server->buffer_size = 0; */
570 /* server->conn_status = 0; */
571 /* server->root_dentry = NULL; */
572 /* server->root_setuped = 0; */
573 mutex_init(&server->root_setup_lock);
574 #ifdef CONFIG_NCPFS_PACKET_SIGNING
575 /* server->sign_wanted = 0; */
576 /* server->sign_active = 0; */
577 #endif
578 init_rwsem(&server->auth_rwsem);
579 server->auth.auth_type = NCP_AUTH_NONE;
580 /* server->auth.object_name_len = 0; */
581 /* server->auth.object_name = NULL; */
582 /* server->auth.object_type = 0; */
583 /* server->priv.len = 0; */
584 /* server->priv.data = NULL; */
586 server->m = data;
587 /* Althought anything producing this is buggy, it happens
588 now because of PATH_MAX changes.. */
589 if (server->m.time_out < 1) {
590 server->m.time_out = 10;
591 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
593 server->m.time_out = server->m.time_out * HZ / 100;
594 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
595 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
597 #ifdef CONFIG_NCPFS_NLS
598 /* load the default NLS charsets */
599 server->nls_vol = load_nls_default();
600 server->nls_io = load_nls_default();
601 #endif /* CONFIG_NCPFS_NLS */
603 atomic_set(&server->dentry_ttl, 0); /* no caching */
605 INIT_LIST_HEAD(&server->tx.requests);
606 mutex_init(&server->rcv.creq_mutex);
607 server->tx.creq = NULL;
608 server->rcv.creq = NULL;
610 init_timer(&server->timeout_tm);
611 #undef NCP_PACKET_SIZE
612 #define NCP_PACKET_SIZE 131072
613 error = -ENOMEM;
614 server->packet_size = NCP_PACKET_SIZE;
615 server->packet = vmalloc(NCP_PACKET_SIZE);
616 if (server->packet == NULL)
617 goto out_nls;
618 server->txbuf = vmalloc(NCP_PACKET_SIZE);
619 if (server->txbuf == NULL)
620 goto out_packet;
621 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
622 if (server->rxbuf == NULL)
623 goto out_txbuf;
625 lock_sock(sock->sk);
626 server->data_ready = sock->sk->sk_data_ready;
627 server->write_space = sock->sk->sk_write_space;
628 server->error_report = sock->sk->sk_error_report;
629 sock->sk->sk_user_data = server;
630 sock->sk->sk_data_ready = ncp_tcp_data_ready;
631 sock->sk->sk_error_report = ncp_tcp_error_report;
632 if (sock->type == SOCK_STREAM) {
633 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
634 server->rcv.len = 10;
635 server->rcv.state = 0;
636 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
637 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
638 sock->sk->sk_write_space = ncp_tcp_write_space;
639 } else {
640 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
641 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
642 server->timeout_tm.data = (unsigned long)server;
643 server->timeout_tm.function = ncpdgram_timeout_call;
645 release_sock(sock->sk);
647 ncp_lock_server(server);
648 error = ncp_connect(server);
649 ncp_unlock_server(server);
650 if (error < 0)
651 goto out_rxbuf;
652 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
654 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
655 #ifdef CONFIG_NCPFS_PACKET_SIGNING
656 if (ncp_negotiate_size_and_options(server, default_bufsize,
657 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
659 if (options != NCP_DEFAULT_OPTIONS)
661 if (ncp_negotiate_size_and_options(server,
662 default_bufsize,
663 options & 2,
664 &(server->buffer_size), &options) != 0)
667 goto out_disconnect;
670 ncp_lock_server(server);
671 if (options & 2)
672 server->sign_wanted = 1;
673 ncp_unlock_server(server);
675 else
676 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
677 if (ncp_negotiate_buffersize(server, default_bufsize,
678 &(server->buffer_size)) != 0)
679 goto out_disconnect;
680 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
682 memset(&finfo, 0, sizeof(finfo));
683 finfo.i.attributes = aDIR;
684 finfo.i.dataStreamSize = 0; /* ignored */
685 finfo.i.dirEntNum = 0;
686 finfo.i.DosDirNum = 0;
687 #ifdef CONFIG_NCPFS_SMALLDOS
688 finfo.i.NSCreator = NW_NS_DOS;
689 #endif
690 finfo.volume = NCP_NUMBER_OF_VOLUMES;
691 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
692 finfo.i.creationTime = finfo.i.modifyTime
693 = cpu_to_le16(0x0000);
694 finfo.i.creationDate = finfo.i.modifyDate
695 = finfo.i.lastAccessDate
696 = cpu_to_le16(0x0C21);
697 finfo.i.nameLen = 0;
698 finfo.i.entryName[0] = '\0';
700 finfo.opened = 0;
701 finfo.ino = 2; /* tradition */
703 server->name_space[finfo.volume] = NW_NS_DOS;
705 error = -ENOMEM;
706 root_inode = ncp_iget(sb, &finfo);
707 if (!root_inode)
708 goto out_disconnect;
709 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
710 sb->s_root = d_alloc_root(root_inode);
711 if (!sb->s_root)
712 goto out_no_root;
713 sb->s_root->d_op = &ncp_root_dentry_operations;
714 return 0;
716 out_no_root:
717 iput(root_inode);
718 out_disconnect:
719 ncp_lock_server(server);
720 ncp_disconnect(server);
721 ncp_unlock_server(server);
722 out_rxbuf:
723 ncp_stop_tasks(server);
724 vfree(server->rxbuf);
725 out_txbuf:
726 vfree(server->txbuf);
727 out_packet:
728 vfree(server->packet);
729 out_nls:
730 #ifdef CONFIG_NCPFS_NLS
731 unload_nls(server->nls_io);
732 unload_nls(server->nls_vol);
733 #endif
734 mutex_destroy(&server->rcv.creq_mutex);
735 mutex_destroy(&server->root_setup_lock);
736 mutex_destroy(&server->mutex);
737 out_fput2:
738 if (server->info_filp)
739 fput(server->info_filp);
740 out_fput:
741 bdi_destroy(&server->bdi);
742 out_bdi:
743 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
745 * The previously used put_filp(ncp_filp); was bogus, since
746 * it doesn't perform proper unlocking.
748 fput(ncp_filp);
749 out:
750 put_pid(data.wdog_pid);
751 sb->s_fs_info = NULL;
752 kfree(server);
753 return error;
756 static void ncp_put_super(struct super_block *sb)
758 struct ncp_server *server = NCP_SBP(sb);
760 ncp_lock_server(server);
761 ncp_disconnect(server);
762 ncp_unlock_server(server);
764 ncp_stop_tasks(server);
766 #ifdef CONFIG_NCPFS_NLS
767 /* unload the NLS charsets */
768 unload_nls(server->nls_vol);
769 unload_nls(server->nls_io);
770 #endif /* CONFIG_NCPFS_NLS */
771 mutex_destroy(&server->rcv.creq_mutex);
772 mutex_destroy(&server->root_setup_lock);
773 mutex_destroy(&server->mutex);
775 if (server->info_filp)
776 fput(server->info_filp);
777 fput(server->ncp_filp);
778 kill_pid(server->m.wdog_pid, SIGTERM, 1);
779 put_pid(server->m.wdog_pid);
781 bdi_destroy(&server->bdi);
782 kfree(server->priv.data);
783 kfree(server->auth.object_name);
784 vfree(server->rxbuf);
785 vfree(server->txbuf);
786 vfree(server->packet);
787 sb->s_fs_info = NULL;
788 kfree(server);
791 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
793 struct dentry* d;
794 struct inode* i;
795 struct ncp_inode_info* ni;
796 struct ncp_server* s;
797 struct ncp_volume_info vi;
798 struct super_block *sb = dentry->d_sb;
799 int err;
800 __u8 dh;
802 d = sb->s_root;
803 if (!d) {
804 goto dflt;
806 i = d->d_inode;
807 if (!i) {
808 goto dflt;
810 ni = NCP_FINFO(i);
811 if (!ni) {
812 goto dflt;
814 s = NCP_SBP(sb);
815 if (!s) {
816 goto dflt;
818 if (!s->m.mounted_vol[0]) {
819 goto dflt;
822 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
823 if (err) {
824 goto dflt;
826 err = ncp_get_directory_info(s, dh, &vi);
827 ncp_dirhandle_free(s, dh);
828 if (err) {
829 goto dflt;
831 buf->f_type = NCP_SUPER_MAGIC;
832 buf->f_bsize = vi.sectors_per_block * 512;
833 buf->f_blocks = vi.total_blocks;
834 buf->f_bfree = vi.free_blocks;
835 buf->f_bavail = vi.free_blocks;
836 buf->f_files = vi.total_dir_entries;
837 buf->f_ffree = vi.available_dir_entries;
838 buf->f_namelen = 12;
839 return 0;
841 /* We cannot say how much disk space is left on a mounted
842 NetWare Server, because free space is distributed over
843 volumes, and the current user might have disk quotas. So
844 free space is not that simple to determine. Our decision
845 here is to err conservatively. */
847 dflt:;
848 buf->f_type = NCP_SUPER_MAGIC;
849 buf->f_bsize = NCP_BLOCK_SIZE;
850 buf->f_blocks = 0;
851 buf->f_bfree = 0;
852 buf->f_bavail = 0;
853 buf->f_namelen = 12;
854 return 0;
857 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
859 struct inode *inode = dentry->d_inode;
860 int result = 0;
861 __le32 info_mask;
862 struct nw_modify_dos_info info;
863 struct ncp_server *server;
865 result = -EIO;
867 server = NCP_SERVER(inode);
868 if (!server) /* How this could happen? */
869 goto out;
871 /* ageing the dentry to force validation */
872 ncp_age_dentry(server, dentry);
874 result = inode_change_ok(inode, attr);
875 if (result < 0)
876 goto out;
878 result = -EPERM;
879 if (((attr->ia_valid & ATTR_UID) &&
880 (attr->ia_uid != server->m.uid)))
881 goto out;
883 if (((attr->ia_valid & ATTR_GID) &&
884 (attr->ia_gid != server->m.gid)))
885 goto out;
887 if (((attr->ia_valid & ATTR_MODE) &&
888 (attr->ia_mode &
889 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
890 goto out;
892 info_mask = 0;
893 memset(&info, 0, sizeof(info));
895 #if 1
896 if ((attr->ia_valid & ATTR_MODE) != 0)
898 umode_t newmode = attr->ia_mode;
900 info_mask |= DM_ATTRIBUTES;
902 if (S_ISDIR(inode->i_mode)) {
903 newmode &= server->m.dir_mode;
904 } else {
905 #ifdef CONFIG_NCPFS_EXTRAS
906 if (server->m.flags & NCP_MOUNT_EXTRAS) {
907 /* any non-default execute bit set */
908 if (newmode & ~server->m.file_mode & S_IXUGO)
909 info.attributes |= aSHARED | aSYSTEM;
910 /* read for group/world and not in default file_mode */
911 else if (newmode & ~server->m.file_mode & S_IRUGO)
912 info.attributes |= aSHARED;
913 } else
914 #endif
915 newmode &= server->m.file_mode;
917 if (newmode & S_IWUGO)
918 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
919 else
920 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
922 #ifdef CONFIG_NCPFS_NFS_NS
923 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
924 result = ncp_modify_nfs_info(server,
925 NCP_FINFO(inode)->volNumber,
926 NCP_FINFO(inode)->dirEntNum,
927 attr->ia_mode, 0);
928 if (result != 0)
929 goto out;
930 info.attributes &= ~(aSHARED | aSYSTEM);
932 /* mark partial success */
933 struct iattr tmpattr;
935 tmpattr.ia_valid = ATTR_MODE;
936 tmpattr.ia_mode = attr->ia_mode;
938 setattr_copy(inode, &tmpattr);
939 mark_inode_dirty(inode);
942 #endif
944 #endif
946 /* Do SIZE before attributes, otherwise mtime together with size does not work...
948 if ((attr->ia_valid & ATTR_SIZE) != 0) {
949 int written;
951 DPRINTK("ncpfs: trying to change size to %ld\n",
952 attr->ia_size);
954 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
955 result = -EACCES;
956 goto out;
958 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
959 attr->ia_size, 0, "", &written);
961 /* According to ndir, the changes only take effect after
962 closing the file */
963 ncp_inode_close(inode);
964 result = ncp_make_closed(inode);
965 if (result)
966 goto out;
968 if (attr->ia_size != i_size_read(inode)) {
969 result = vmtruncate(inode, attr->ia_size);
970 if (result)
971 goto out;
972 mark_inode_dirty(inode);
975 if ((attr->ia_valid & ATTR_CTIME) != 0) {
976 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
977 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
978 &info.creationTime, &info.creationDate);
980 if ((attr->ia_valid & ATTR_MTIME) != 0) {
981 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
982 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
983 &info.modifyTime, &info.modifyDate);
985 if ((attr->ia_valid & ATTR_ATIME) != 0) {
986 __le16 dummy;
987 info_mask |= (DM_LAST_ACCESS_DATE);
988 ncp_date_unix2dos(attr->ia_atime.tv_sec,
989 &dummy, &info.lastAccessDate);
991 if (info_mask != 0) {
992 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
993 inode, info_mask, &info);
994 if (result != 0) {
995 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
996 /* NetWare seems not to allow this. I
997 do not know why. So, just tell the
998 user everything went fine. This is
999 a terrible hack, but I do not know
1000 how to do this correctly. */
1001 result = 0;
1002 } else
1003 goto out;
1005 #ifdef CONFIG_NCPFS_STRONG
1006 if ((!result) && (info_mask & DM_ATTRIBUTES))
1007 NCP_FINFO(inode)->nwattr = info.attributes;
1008 #endif
1010 if (result)
1011 goto out;
1013 setattr_copy(inode, attr);
1014 mark_inode_dirty(inode);
1016 out:
1017 if (result > 0)
1018 result = -EACCES;
1019 return result;
1022 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1023 int flags, const char *dev_name, void *data)
1025 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1028 static struct file_system_type ncp_fs_type = {
1029 .owner = THIS_MODULE,
1030 .name = "ncpfs",
1031 .mount = ncp_mount,
1032 .kill_sb = kill_anon_super,
1033 .fs_flags = FS_BINARY_MOUNTDATA,
1036 static int __init init_ncp_fs(void)
1038 int err;
1039 DPRINTK("ncpfs: init_ncp_fs called\n");
1041 err = init_inodecache();
1042 if (err)
1043 goto out1;
1044 err = register_filesystem(&ncp_fs_type);
1045 if (err)
1046 goto out;
1047 return 0;
1048 out:
1049 destroy_inodecache();
1050 out1:
1051 return err;
1054 static void __exit exit_ncp_fs(void)
1056 DPRINTK("ncpfs: exit_ncp_fs called\n");
1057 unregister_filesystem(&ncp_fs_type);
1058 destroy_inodecache();
1061 module_init(init_ncp_fs)
1062 module_exit(exit_ncp_fs)
1063 MODULE_LICENSE("GPL");