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