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