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