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