Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[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/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         unload_nls(server->nls_vol);
750         unload_nls(server->nls_io);
751 #endif /* CONFIG_NCPFS_NLS */
752
753         if (server->info_filp)
754                 fput(server->info_filp);
755         fput(server->ncp_filp);
756         kill_pid(server->m.wdog_pid, SIGTERM, 1);
757         put_pid(server->m.wdog_pid);
758
759         kfree(server->priv.data);
760         kfree(server->auth.object_name);
761         vfree(server->rxbuf);
762         vfree(server->txbuf);
763         vfree(server->packet);
764         sb->s_fs_info = NULL;
765         kfree(server);
766
767         unlock_kernel();
768 }
769
770 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
771 {
772         struct dentry* d;
773         struct inode* i;
774         struct ncp_inode_info* ni;
775         struct ncp_server* s;
776         struct ncp_volume_info vi;
777         struct super_block *sb = dentry->d_sb;
778         int err;
779         __u8 dh;
780         
781         d = sb->s_root;
782         if (!d) {
783                 goto dflt;
784         }
785         i = d->d_inode;
786         if (!i) {
787                 goto dflt;
788         }
789         ni = NCP_FINFO(i);
790         if (!ni) {
791                 goto dflt;
792         }
793         s = NCP_SBP(sb);
794         if (!s) {
795                 goto dflt;
796         }
797         if (!s->m.mounted_vol[0]) {
798                 goto dflt;
799         }
800
801         err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
802         if (err) {
803                 goto dflt;
804         }
805         err = ncp_get_directory_info(s, dh, &vi);
806         ncp_dirhandle_free(s, dh);
807         if (err) {
808                 goto dflt;
809         }
810         buf->f_type = NCP_SUPER_MAGIC;
811         buf->f_bsize = vi.sectors_per_block * 512;
812         buf->f_blocks = vi.total_blocks;
813         buf->f_bfree = vi.free_blocks;
814         buf->f_bavail = vi.free_blocks;
815         buf->f_files = vi.total_dir_entries;
816         buf->f_ffree = vi.available_dir_entries;
817         buf->f_namelen = 12;
818         return 0;
819
820         /* We cannot say how much disk space is left on a mounted
821            NetWare Server, because free space is distributed over
822            volumes, and the current user might have disk quotas. So
823            free space is not that simple to determine. Our decision
824            here is to err conservatively. */
825
826 dflt:;
827         buf->f_type = NCP_SUPER_MAGIC;
828         buf->f_bsize = NCP_BLOCK_SIZE;
829         buf->f_blocks = 0;
830         buf->f_bfree = 0;
831         buf->f_bavail = 0;
832         buf->f_namelen = 12;
833         return 0;
834 }
835
836 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
837 {
838         struct inode *inode = dentry->d_inode;
839         int result = 0;
840         __le32 info_mask;
841         struct nw_modify_dos_info info;
842         struct ncp_server *server;
843
844         result = -EIO;
845
846         lock_kernel();  
847
848         server = NCP_SERVER(inode);
849         if ((!server) || !ncp_conn_valid(server))
850                 goto out;
851
852         /* ageing the dentry to force validation */
853         ncp_age_dentry(server, dentry);
854
855         result = inode_change_ok(inode, attr);
856         if (result < 0)
857                 goto out;
858
859         result = -EPERM;
860         if (((attr->ia_valid & ATTR_UID) &&
861              (attr->ia_uid != server->m.uid)))
862                 goto out;
863
864         if (((attr->ia_valid & ATTR_GID) &&
865              (attr->ia_gid != server->m.gid)))
866                 goto out;
867
868         if (((attr->ia_valid & ATTR_MODE) &&
869              (attr->ia_mode &
870               ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
871                 goto out;
872
873         info_mask = 0;
874         memset(&info, 0, sizeof(info));
875
876 #if 1 
877         if ((attr->ia_valid & ATTR_MODE) != 0)
878         {
879                 umode_t newmode = attr->ia_mode;
880
881                 info_mask |= DM_ATTRIBUTES;
882
883                 if (S_ISDIR(inode->i_mode)) {
884                         newmode &= server->m.dir_mode;
885                 } else {
886 #ifdef CONFIG_NCPFS_EXTRAS                      
887                         if (server->m.flags & NCP_MOUNT_EXTRAS) {
888                                 /* any non-default execute bit set */
889                                 if (newmode & ~server->m.file_mode & S_IXUGO)
890                                         info.attributes |= aSHARED | aSYSTEM;
891                                 /* read for group/world and not in default file_mode */
892                                 else if (newmode & ~server->m.file_mode & S_IRUGO)
893                                         info.attributes |= aSHARED;
894                         } else
895 #endif
896                                 newmode &= server->m.file_mode;                 
897                 }
898                 if (newmode & S_IWUGO)
899                         info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
900                 else
901                         info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
902
903 #ifdef CONFIG_NCPFS_NFS_NS
904                 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
905                         result = ncp_modify_nfs_info(server,
906                                                      NCP_FINFO(inode)->volNumber,
907                                                      NCP_FINFO(inode)->dirEntNum,
908                                                      attr->ia_mode, 0);
909                         if (result != 0)
910                                 goto out;
911                         info.attributes &= ~(aSHARED | aSYSTEM);
912                         {
913                                 /* mark partial success */
914                                 struct iattr tmpattr;
915                                 
916                                 tmpattr.ia_valid = ATTR_MODE;
917                                 tmpattr.ia_mode = attr->ia_mode;
918
919                                 result = inode_setattr(inode, &tmpattr);
920                                 if (result)
921                                         goto out;
922                         }
923                 }
924 #endif
925         }
926 #endif
927
928         /* Do SIZE before attributes, otherwise mtime together with size does not work...
929          */
930         if ((attr->ia_valid & ATTR_SIZE) != 0) {
931                 int written;
932
933                 DPRINTK("ncpfs: trying to change size to %ld\n",
934                         attr->ia_size);
935
936                 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
937                         result = -EACCES;
938                         goto out;
939                 }
940                 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
941                           attr->ia_size, 0, "", &written);
942
943                 /* According to ndir, the changes only take effect after
944                    closing the file */
945                 ncp_inode_close(inode);
946                 result = ncp_make_closed(inode);
947                 if (result)
948                         goto out;
949                 {
950                         struct iattr tmpattr;
951                         
952                         tmpattr.ia_valid = ATTR_SIZE;
953                         tmpattr.ia_size = attr->ia_size;
954                         
955                         result = inode_setattr(inode, &tmpattr);
956                         if (result)
957                                 goto out;
958                 }
959         }
960         if ((attr->ia_valid & ATTR_CTIME) != 0) {
961                 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
962                 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
963                              &info.creationTime, &info.creationDate);
964         }
965         if ((attr->ia_valid & ATTR_MTIME) != 0) {
966                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
967                 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
968                                   &info.modifyTime, &info.modifyDate);
969         }
970         if ((attr->ia_valid & ATTR_ATIME) != 0) {
971                 __le16 dummy;
972                 info_mask |= (DM_LAST_ACCESS_DATE);
973                 ncp_date_unix2dos(attr->ia_atime.tv_sec,
974                                   &dummy, &info.lastAccessDate);
975         }
976         if (info_mask != 0) {
977                 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
978                                       inode, info_mask, &info);
979                 if (result != 0) {
980                         result = -EACCES;
981
982                         if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
983                                 /* NetWare seems not to allow this. I
984                                    do not know why. So, just tell the
985                                    user everything went fine. This is
986                                    a terrible hack, but I do not know
987                                    how to do this correctly. */
988                                 result = 0;
989                         } else
990                                 goto out;
991                 }
992 #ifdef CONFIG_NCPFS_STRONG              
993                 if ((!result) && (info_mask & DM_ATTRIBUTES))
994                         NCP_FINFO(inode)->nwattr = info.attributes;
995 #endif
996         }
997         if (!result)
998                 result = inode_setattr(inode, attr);
999 out:
1000         unlock_kernel();
1001         return result;
1002 }
1003
1004 static int ncp_get_sb(struct file_system_type *fs_type,
1005         int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1006 {
1007         return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
1008 }
1009
1010 static struct file_system_type ncp_fs_type = {
1011         .owner          = THIS_MODULE,
1012         .name           = "ncpfs",
1013         .get_sb         = ncp_get_sb,
1014         .kill_sb        = kill_anon_super,
1015         .fs_flags       = FS_BINARY_MOUNTDATA,
1016 };
1017
1018 static int __init init_ncp_fs(void)
1019 {
1020         int err;
1021         DPRINTK("ncpfs: init_ncp_fs called\n");
1022
1023         err = init_inodecache();
1024         if (err)
1025                 goto out1;
1026         err = register_filesystem(&ncp_fs_type);
1027         if (err)
1028                 goto out;
1029         return 0;
1030 out:
1031         destroy_inodecache();
1032 out1:
1033         return err;
1034 }
1035
1036 static void __exit exit_ncp_fs(void)
1037 {
1038         DPRINTK("ncpfs: exit_ncp_fs called\n");
1039         unregister_filesystem(&ncp_fs_type);
1040         destroy_inodecache();
1041 }
1042
1043 module_init(init_ncp_fs)
1044 module_exit(exit_ncp_fs)
1045 MODULE_LICENSE("GPL");