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