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