Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / fs / ncpfs / inode.c
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
12 #include <linux/module.h>
13
14 #include <asm/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
17
18 #include <linux/time.h>
19 #include <linux/kernel.h>
20 #include <linux/mm.h>
21 #include <linux/string.h>
22 #include <linux/stat.h>
23 #include <linux/errno.h>
24 #include <linux/file.h>
25 #include <linux/fcntl.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/init.h>
29 #include <linux/vfs.h>
30 #include <linux/mount.h>
31 #include <linux/seq_file.h>
32
33 #include <linux/ncp_fs.h>
34
35 #include <net/sock.h>
36
37 #include "ncplib_kernel.h"
38 #include "getopt.h"
39
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
45 static void ncp_evict_inode(struct inode *);
46 static void ncp_put_super(struct super_block *);
47 static int ncp_statfs(struct dentry *, struct kstatfs *);
48 static int ncp_show_options(struct seq_file *, struct vfsmount *);
49
50 static struct kmem_cache * ncp_inode_cachep;
51
52 static struct inode *ncp_alloc_inode(struct super_block *sb)
53 {
54 struct ncp_inode_info *ei;
55 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
56 if (!ei)
57 return NULL;
58 return &ei->vfs_inode;
59 }
60
61 static void ncp_destroy_inode(struct inode *inode)
62 {
63 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
64 }
65
66 static void init_once(void *foo)
67 {
68 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
69
70 mutex_init(&ei->open_mutex);
71 inode_init_once(&ei->vfs_inode);
72 }
73
74 static int init_inodecache(void)
75 {
76 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
77 sizeof(struct ncp_inode_info),
78 0, (SLAB_RECLAIM_ACCOUNT|
79 SLAB_MEM_SPREAD),
80 init_once);
81 if (ncp_inode_cachep == NULL)
82 return -ENOMEM;
83 return 0;
84 }
85
86 static void destroy_inodecache(void)
87 {
88 kmem_cache_destroy(ncp_inode_cachep);
89 }
90
91 static int ncp_remount(struct super_block *sb, int *flags, char* data)
92 {
93 *flags |= MS_NODIRATIME;
94 return 0;
95 }
96
97 static const struct super_operations ncp_sops =
98 {
99 .alloc_inode = ncp_alloc_inode,
100 .destroy_inode = ncp_destroy_inode,
101 .drop_inode = generic_delete_inode,
102 .evict_inode = ncp_evict_inode,
103 .put_super = ncp_put_super,
104 .statfs = ncp_statfs,
105 .remount_fs = ncp_remount,
106 .show_options = ncp_show_options,
107 };
108
109 /*
110 * Fill in the ncpfs-specific information in the inode.
111 */
112 static 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
119 void 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
131 static 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
141 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
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
151 static 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 ??? */
160 i_size_write(inode, NCP_BLOCK_SIZE);
161 } else {
162 u32 size;
163
164 inode->i_mode = server->m.file_mode;
165 size = le32_to_cpu(nwi->dataStreamSize);
166 i_size_write(inode, size);
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) {
173 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
174 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
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
200 void 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 /*
213 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
214 */
215 static 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;
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)
234 static const struct inode_operations ncp_symlink_inode_operations = {
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 */
245 struct inode *
246 ncp_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
259 inode->i_mapping->backing_dev_info = sb->s_bdi;
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
287 static void
288 ncp_evict_inode(struct inode *inode)
289 {
290 truncate_inode_pages(&inode->i_data, 0);
291 end_writeback(inode);
292
293 if (S_ISDIR(inode->i_mode)) {
294 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
295 }
296
297 if (ncp_make_closed(inode) != 0) {
298 /* We can't do anything but complain. */
299 printk(KERN_ERR "ncp_evict_inode: could not close\n");
300 }
301 }
302
303 static void ncp_stop_tasks(struct ncp_server *server) {
304 struct sock* sk = server->ncp_sock->sk;
305
306 lock_sock(sk);
307 sk->sk_error_report = server->error_report;
308 sk->sk_data_ready = server->data_ready;
309 sk->sk_write_space = server->write_space;
310 release_sock(sk);
311 del_timer_sync(&server->timeout_tm);
312 flush_scheduled_work();
313 }
314
315 static 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
346 static 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
361 static 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;
366 int ret;
367
368 data->flags = 0;
369 data->int_flags = 0;
370 data->mounted_uid = 0;
371 data->wdog_pid = NULL;
372 data->ncp_fd = ~0;
373 data->time_out = NCP_DEFAULT_TIME_OUT;
374 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
375 data->uid = 0;
376 data->gid = 0;
377 data->file_mode = NCP_DEFAULT_FILE_MODE;
378 data->dir_mode = NCP_DEFAULT_DIR_MODE;
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) {
383 ret = optval;
384 if (ret < 0)
385 goto err;
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':
412 data->wdog_pid = find_get_pid(optint);
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':
421 ret = -ECHRNG;
422 if (optint < NCP_MOUNT_VERSION_V4)
423 goto err;
424 if (optint > NCP_MOUNT_VERSION_V5)
425 goto err;
426 version = optint;
427 break;
428
429 }
430 }
431 return 0;
432 err:
433 put_pid(data->wdog_pid);
434 data->wdog_pid = NULL;
435 return ret;
436 }
437
438 static 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
453 data.wdog_pid = NULL;
454 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
455 if (!server)
456 return -ENOMEM;
457 sb->s_fs_info = server;
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;
470 data.wdog_pid = find_get_pid(md->wdog_pid);
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;
490 data.wdog_pid = find_get_pid(md->wdog_pid);
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;
516 sock_inode = ncp_filp->f_path.dentry->d_inode;
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;
534 sb->s_bdi = &server->bdi;
535
536 server = NCP_SBP(sb);
537 memset(server, 0, sizeof(*server));
538
539 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
540 if (error)
541 goto out_bdi;
542
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;
554 sock_inode = server->info_filp->f_path.dentry->d_inode;
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; */
567 mutex_init(&server->mutex);
568 server->packet = NULL;
569 /* server->buffer_size = 0; */
570 /* server->conn_status = 0; */
571 /* server->root_dentry = NULL; */
572 /* server->root_setuped = 0; */
573 mutex_init(&server->root_setup_lock);
574 #ifdef CONFIG_NCPFS_PACKET_SIGNING
575 /* server->sign_wanted = 0; */
576 /* server->sign_active = 0; */
577 #endif
578 init_rwsem(&server->auth_rwsem);
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
603 atomic_set(&server->dentry_ttl, 0); /* no caching */
604
605 INIT_LIST_HEAD(&server->tx.requests);
606 mutex_init(&server->rcv.creq_mutex);
607 server->tx.creq = NULL;
608 server->rcv.creq = NULL;
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;
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;
624
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;
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;
636 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
637 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
638 sock->sk->sk_write_space = ncp_tcp_write_space;
639 } else {
640 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
641 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
642 server->timeout_tm.data = (unsigned long)server;
643 server->timeout_tm.function = ncpdgram_timeout_call;
644 }
645 release_sock(sock->sk);
646
647 ncp_lock_server(server);
648 error = ncp_connect(server);
649 ncp_unlock_server(server);
650 if (error < 0)
651 goto out_rxbuf;
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 }
670 ncp_lock_server(server);
671 if (options & 2)
672 server->sign_wanted = 1;
673 ncp_unlock_server(server);
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
716 out_no_root:
717 iput(root_inode);
718 out_disconnect:
719 ncp_lock_server(server);
720 ncp_disconnect(server);
721 ncp_unlock_server(server);
722 out_rxbuf:
723 ncp_stop_tasks(server);
724 vfree(server->rxbuf);
725 out_txbuf:
726 vfree(server->txbuf);
727 out_packet:
728 vfree(server->packet);
729 out_nls:
730 #ifdef CONFIG_NCPFS_NLS
731 unload_nls(server->nls_io);
732 unload_nls(server->nls_vol);
733 #endif
734 mutex_destroy(&server->rcv.creq_mutex);
735 mutex_destroy(&server->root_setup_lock);
736 mutex_destroy(&server->mutex);
737 out_fput2:
738 if (server->info_filp)
739 fput(server->info_filp);
740 out_fput:
741 bdi_destroy(&server->bdi);
742 out_bdi:
743 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
744 *
745 * The previously used put_filp(ncp_filp); was bogus, since
746 * it doesn't perform proper unlocking.
747 */
748 fput(ncp_filp);
749 out:
750 put_pid(data.wdog_pid);
751 sb->s_fs_info = NULL;
752 kfree(server);
753 return error;
754 }
755
756 static 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 */
768 unload_nls(server->nls_vol);
769 unload_nls(server->nls_io);
770 #endif /* CONFIG_NCPFS_NLS */
771 mutex_destroy(&server->rcv.creq_mutex);
772 mutex_destroy(&server->root_setup_lock);
773 mutex_destroy(&server->mutex);
774
775 if (server->info_filp)
776 fput(server->info_filp);
777 fput(server->ncp_filp);
778 kill_pid(server->m.wdog_pid, SIGTERM, 1);
779 put_pid(server->m.wdog_pid);
780
781 bdi_destroy(&server->bdi);
782 kfree(server->priv.data);
783 kfree(server->auth.object_name);
784 vfree(server->rxbuf);
785 vfree(server->txbuf);
786 vfree(server->packet);
787 sb->s_fs_info = NULL;
788 kfree(server);
789 }
790
791 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
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;
798 struct super_block *sb = dentry->d_sb;
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
847 dflt:;
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
857 int 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
867 server = NCP_SERVER(inode);
868 if (!server) /* How this could happen? */
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
938 setattr_copy(inode, &tmpattr);
939 mark_inode_dirty(inode);
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;
967
968 if (attr->ia_size != i_size_read(inode)) {
969 result = vmtruncate(inode, attr->ia_size);
970 if (result)
971 goto out;
972 mark_inode_dirty(inode);
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) {
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 }
1010 if (result)
1011 goto out;
1012
1013 setattr_copy(inode, attr);
1014 mark_inode_dirty(inode);
1015
1016 out:
1017 if (result > 0)
1018 result = -EACCES;
1019 return result;
1020 }
1021
1022 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1023 int flags, const char *dev_name, void *data)
1024 {
1025 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1026 }
1027
1028 static struct file_system_type ncp_fs_type = {
1029 .owner = THIS_MODULE,
1030 .name = "ncpfs",
1031 .mount = ncp_mount,
1032 .kill_sb = kill_anon_super,
1033 .fs_flags = FS_BINARY_MOUNTDATA,
1034 };
1035
1036 static int __init init_ncp_fs(void)
1037 {
1038 int err;
1039 DPRINTK("ncpfs: init_ncp_fs called\n");
1040
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;
1048 out:
1049 destroy_inodecache();
1050 out1:
1051 return err;
1052 }
1053
1054 static void __exit exit_ncp_fs(void)
1055 {
1056 DPRINTK("ncpfs: exit_ncp_fs called\n");
1057 unregister_filesystem(&ncp_fs_type);
1058 destroy_inodecache();
1059 }
1060
1061 module_init(init_ncp_fs)
1062 module_exit(exit_ncp_fs)
1063 MODULE_LICENSE("GPL");
This page took 0.051967 seconds and 5 git commands to generate.