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