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