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