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