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