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