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