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