workqueue: gut system_nrt[_freezable]_wq()
[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{
1a1d92c1 92 kmem_cache_destroy(ncp_inode_cachep);
1da177e4
LT
93}
94
95static int ncp_remount(struct super_block *sb, int *flags, char* data)
96{
97 *flags |= MS_NODIRATIME;
98 return 0;
99}
100
ee9b6d61 101static const struct super_operations ncp_sops =
1da177e4
LT
102{
103 .alloc_inode = ncp_alloc_inode,
104 .destroy_inode = ncp_destroy_inode,
105 .drop_inode = generic_delete_inode,
94ee8494 106 .evict_inode = ncp_evict_inode,
1da177e4
LT
107 .put_super = ncp_put_super,
108 .statfs = ncp_statfs,
109 .remount_fs = ncp_remount,
564cd138 110 .show_options = ncp_show_options,
1da177e4
LT
111};
112
1da177e4
LT
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
2e54eb96 145 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
1da177e4
LT
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 ??? */
2e54eb96 164 i_size_write(inode, NCP_BLOCK_SIZE);
1da177e4 165 } else {
2e54eb96
PV
166 u32 size;
167
1da177e4 168 inode->i_mode = server->m.file_mode;
2e54eb96
PV
169 size = le32_to_cpu(nwi->dataStreamSize);
170 i_size_write(inode, size);
1da177e4
LT
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) {
2e54eb96
PV
177 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
178 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
1da177e4
LT
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/*
2e54eb96 217 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
1da177e4
LT
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
bfe86848 229 set_nlink(inode, 1);
1da177e4
LT
230 inode->i_uid = server->m.uid;
231 inode->i_gid = server->m.gid;
1da177e4
LT
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)
92e1d5be 238static const struct inode_operations ncp_symlink_inode_operations = {
1da177e4
LT
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
2e54eb96 263 inode->i_mapping->backing_dev_info = sb->s_bdi;
1da177e4
LT
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
94ee8494 292ncp_evict_inode(struct inode *inode)
1da177e4 293{
fef26658 294 truncate_inode_pages(&inode->i_data, 0);
dbd5768f 295 clear_inode(inode);
fef26658 296
1da177e4 297 if (S_ISDIR(inode->i_mode)) {
94ee8494 298 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
1da177e4
LT
299 }
300
301 if (ncp_make_closed(inode) != 0) {
302 /* We can't do anything but complain. */
94ee8494 303 printk(KERN_ERR "ncp_evict_inode: could not close\n");
1da177e4 304 }
1da177e4
LT
305}
306
307static void ncp_stop_tasks(struct ncp_server *server) {
308 struct sock* sk = server->ncp_sock->sk;
2a4df5d3
PV
309
310 lock_sock(sk);
1da177e4
LT
311 sk->sk_error_report = server->error_report;
312 sk->sk_data_ready = server->data_ready;
313 sk->sk_write_space = server->write_space;
2a4df5d3 314 release_sock(sk);
1da177e4 315 del_timer_sync(&server->timeout_tm);
5d8e4bdd
TH
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);
1da177e4
LT
322}
323
34c80b1d 324static int ncp_show_options(struct seq_file *seq, struct dentry *root)
564cd138 325{
34c80b1d 326 struct ncp_server *server = NCP_SBP(root->d_sb);
564cd138
MS
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
1da177e4
LT
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;
1de24126 375 int ret;
1da177e4
LT
376
377 data->flags = 0;
378 data->int_flags = 0;
379 data->mounted_uid = 0;
2154227a 380 data->wdog_pid = NULL;
1da177e4 381 data->ncp_fd = ~0;
564cd138
MS
382 data->time_out = NCP_DEFAULT_TIME_OUT;
383 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
1da177e4
LT
384 data->uid = 0;
385 data->gid = 0;
564cd138
MS
386 data->file_mode = NCP_DEFAULT_FILE_MODE;
387 data->dir_mode = NCP_DEFAULT_DIR_MODE;
1da177e4
LT
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) {
1de24126
EB
392 ret = optval;
393 if (ret < 0)
394 goto err;
1da177e4
LT
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':
2154227a 421 data->wdog_pid = find_get_pid(optint);
1da177e4
LT
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':
1de24126
EB
430 ret = -ECHRNG;
431 if (optint < NCP_MOUNT_VERSION_V4)
432 goto err;
433 if (optint > NCP_MOUNT_VERSION_V5)
434 goto err;
1da177e4
LT
435 version = optint;
436 break;
437
438 }
439 }
440 return 0;
1de24126
EB
441err:
442 put_pid(data->wdog_pid);
443 data->wdog_pid = NULL;
444 return ret;
1da177e4
LT
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
2a5cac17 462 memset(&data, 0, sizeof(data));
f8314dc6 463 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
1da177e4
LT
464 if (!server)
465 return -ENOMEM;
466 sb->s_fs_info = server;
1da177e4
LT
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;
2154227a 479 data.wdog_pid = find_get_pid(md->wdog_pid);
1da177e4
LT
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;
1da177e4 497 data.mounted_uid = md->mounted_uid;
2154227a 498 data.wdog_pid = find_get_pid(md->wdog_pid);
1da177e4
LT
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;
1da177e4
LT
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;
92e5baef 523 sock_inode = ncp_filp->f_path.dentry->d_inode;
1da177e4
LT
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;
0378c405 541 sb->s_d_op = &ncp_dentry_operations;
f1970c73 542 sb->s_bdi = &server->bdi;
1da177e4
LT
543
544 server = NCP_SBP(sb);
545 memset(server, 0, sizeof(*server));
546
f1970c73
JA
547 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
548 if (error)
759c361e 549 goto out_fput;
f1970c73 550
1da177e4
LT
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)
759c361e 560 goto out_bdi;
1da177e4 561 error = -ENOTSOCK;
92e5baef 562 sock_inode = server->info_filp->f_path.dentry->d_inode;
1da177e4
LT
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; */
8e3f9045 575 mutex_init(&server->mutex);
1da177e4
LT
576 server->packet = NULL;
577/* server->buffer_size = 0; */
578/* server->conn_status = 0; */
579/* server->root_dentry = NULL; */
580/* server->root_setuped = 0; */
2e54eb96 581 mutex_init(&server->root_setup_lock);
1da177e4
LT
582#ifdef CONFIG_NCPFS_PACKET_SIGNING
583/* server->sign_wanted = 0; */
584/* server->sign_active = 0; */
585#endif
2e54eb96 586 init_rwsem(&server->auth_rwsem);
1da177e4
LT
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;
25985edc 595 /* Although anything producing this is buggy, it happens
1da177e4
LT
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
2e54eb96 611 atomic_set(&server->dentry_ttl, 0); /* no caching */
1da177e4
LT
612
613 INIT_LIST_HEAD(&server->tx.requests);
8e3f9045 614 mutex_init(&server->rcv.creq_mutex);
1da177e4
LT
615 server->tx.creq = NULL;
616 server->rcv.creq = NULL;
1da177e4
LT
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;
c5f93cf1
PO
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;
1da177e4 632
2a4df5d3
PV
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;
1da177e4
LT
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;
c4028958
DH
644 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
645 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
1da177e4
LT
646 sock->sk->sk_write_space = ncp_tcp_write_space;
647 } else {
c4028958
DH
648 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
649 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
1da177e4
LT
650 server->timeout_tm.data = (unsigned long)server;
651 server->timeout_tm.function = ncpdgram_timeout_call;
652 }
2a4df5d3 653 release_sock(sock->sk);
1da177e4
LT
654
655 ncp_lock_server(server);
656 error = ncp_connect(server);
657 ncp_unlock_server(server);
658 if (error < 0)
c5f93cf1 659 goto out_rxbuf;
1da177e4
LT
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 }
2e54eb96 678 ncp_lock_server(server);
1da177e4
LT
679 if (options & 2)
680 server->sign_wanted = 1;
2e54eb96 681 ncp_unlock_server(server);
1da177e4
LT
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);
48fde701 718 sb->s_root = d_make_root(root_inode);
1da177e4 719 if (!sb->s_root)
48fde701 720 goto out_disconnect;
1da177e4
LT
721 return 0;
722
1da177e4
LT
723out_disconnect:
724 ncp_lock_server(server);
725 ncp_disconnect(server);
726 ncp_unlock_server(server);
c5f93cf1 727out_rxbuf:
1da177e4 728 ncp_stop_tasks(server);
c5f93cf1
PO
729 vfree(server->rxbuf);
730out_txbuf:
731 vfree(server->txbuf);
732out_packet:
1da177e4
LT
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
2e54eb96
PV
739 mutex_destroy(&server->rcv.creq_mutex);
740 mutex_destroy(&server->root_setup_lock);
741 mutex_destroy(&server->mutex);
1da177e4
LT
742out_fput2:
743 if (server->info_filp)
744 fput(server->info_filp);
f1970c73 745out_bdi:
759c361e
DH
746 bdi_destroy(&server->bdi);
747out_fput:
1da177e4
LT
748 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
749 *
e956b4b7
MW
750 * The previously used put_filp(ncp_filp); was bogus, since
751 * it doesn't perform proper unlocking.
1da177e4
LT
752 */
753 fput(ncp_filp);
754out:
1de24126 755 put_pid(data.wdog_pid);
1da177e4
LT
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 */
6d729e44
TG
773 unload_nls(server->nls_vol);
774 unload_nls(server->nls_io);
1da177e4 775#endif /* CONFIG_NCPFS_NLS */
2e54eb96
PV
776 mutex_destroy(&server->rcv.creq_mutex);
777 mutex_destroy(&server->root_setup_lock);
778 mutex_destroy(&server->mutex);
1da177e4
LT
779
780 if (server->info_filp)
781 fput(server->info_filp);
782 fput(server->ncp_filp);
2154227a
EB
783 kill_pid(server->m.wdog_pid, SIGTERM, 1);
784 put_pid(server->m.wdog_pid);
1da177e4 785
f1970c73 786 bdi_destroy(&server->bdi);
44db77f3
PE
787 kfree(server->priv.data);
788 kfree(server->auth.object_name);
c5f93cf1
PO
789 vfree(server->rxbuf);
790 vfree(server->txbuf);
1da177e4
LT
791 vfree(server->packet);
792 sb->s_fs_info = NULL;
793 kfree(server);
794}
795
726c3342 796static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4
LT
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;
726c3342 803 struct super_block *sb = dentry->d_sb;
1da177e4
LT
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
1da177e4 872 server = NCP_SERVER(inode);
2e54eb96 873 if (!server) /* How this could happen? */
1da177e4
LT
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
1025774c
CH
943 setattr_copy(inode, &tmpattr);
944 mark_inode_dirty(inode);
1da177e4
LT
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;
1025774c
CH
972
973 if (attr->ia_size != i_size_read(inode)) {
974 result = vmtruncate(inode, attr->ia_size);
1da177e4
LT
975 if (result)
976 goto out;
1025774c 977 mark_inode_dirty(inode);
1da177e4
LT
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) {
1da177e4
LT
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 }
1025774c
CH
1015 if (result)
1016 goto out;
1017
1018 setattr_copy(inode, attr);
1019 mark_inode_dirty(inode);
1020
1da177e4 1021out:
2e54eb96
PV
1022 if (result > 0)
1023 result = -EACCES;
1da177e4
LT
1024 return result;
1025}
1026
3c26ff6e
AV
1027static struct dentry *ncp_mount(struct file_system_type *fs_type,
1028 int flags, const char *dev_name, void *data)
1da177e4 1029{
3c26ff6e 1030 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1da177e4
LT
1031}
1032
1033static struct file_system_type ncp_fs_type = {
1034 .owner = THIS_MODULE,
1035 .name = "ncpfs",
3c26ff6e 1036 .mount = ncp_mount,
1da177e4 1037 .kill_sb = kill_anon_super,
564cd138 1038 .fs_flags = FS_BINARY_MOUNTDATA,
1da177e4
LT
1039};
1040
1041static int __init init_ncp_fs(void)
1042{
1043 int err;
7c28cbae 1044 DPRINTK("ncpfs: init_ncp_fs called\n");
1da177e4 1045
1da177e4
LT
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{
7c28cbae 1061 DPRINTK("ncpfs: exit_ncp_fs called\n");
1da177e4
LT
1062 unregister_filesystem(&ncp_fs_type);
1063 destroy_inodecache();
1da177e4
LT
1064}
1065
1066module_init(init_ncp_fs)
1067module_exit(exit_ncp_fs)
1068MODULE_LICENSE("GPL");
This page took 0.657872 seconds and 5 git commands to generate.