Merge remote-tracking branch 'asoc/fix/dma' into asoc-linus
[linux-drm-fsl-dcu.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                                         ret = -EINVAL;
408                                         goto err;
409                                 }
410                                 break;
411                         case 'g':
412                                 data->gid = make_kgid(current_user_ns(), optint);
413                                 if (!gid_valid(data->gid)) {
414                                         ret = -EINVAL;
415                                         goto err;
416                                 }
417                                 break;
418                         case 'o':
419                                 data->mounted_uid = make_kuid(current_user_ns(), optint);
420                                 if (!uid_valid(data->mounted_uid)) {
421                                         ret = -EINVAL;
422                                         goto err;
423                                 }
424                                 break;
425                         case 'm':
426                                 data->file_mode = optint;
427                                 break;
428                         case 'd':
429                                 data->dir_mode = optint;
430                                 break;
431                         case 't':
432                                 data->time_out = optint;
433                                 break;
434                         case 'r':
435                                 data->retry_count = optint;
436                                 break;
437                         case 'f':
438                                 data->flags = optint;
439                                 break;
440                         case 'w':
441                                 data->wdog_pid = find_get_pid(optint);
442                                 break;
443                         case 'n':
444                                 data->ncp_fd = optint;
445                                 break;
446                         case 'i':
447                                 data->info_fd = optint;
448                                 break;
449                         case 'v':
450                                 ret = -ECHRNG;
451                                 if (optint < NCP_MOUNT_VERSION_V4)
452                                         goto err;
453                                 if (optint > NCP_MOUNT_VERSION_V5)
454                                         goto err;
455                                 version = optint;
456                                 break;
457                         
458                 }
459         }
460         return 0;
461 err:
462         put_pid(data->wdog_pid);
463         data->wdog_pid = NULL;
464         return ret;
465 }
466
467 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
468 {
469         struct ncp_mount_data_kernel data;
470         struct ncp_server *server;
471         struct file *ncp_filp;
472         struct inode *root_inode;
473         struct inode *sock_inode;
474         struct socket *sock;
475         int error;
476         int default_bufsize;
477 #ifdef CONFIG_NCPFS_PACKET_SIGNING
478         int options;
479 #endif
480         struct ncp_entry_info finfo;
481
482         memset(&data, 0, sizeof(data));
483         server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
484         if (!server)
485                 return -ENOMEM;
486         sb->s_fs_info = server;
487
488         error = -EFAULT;
489         if (raw_data == NULL)
490                 goto out;
491         switch (*(int*)raw_data) {
492                 case NCP_MOUNT_VERSION:
493                         {
494                                 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
495
496                                 data.flags = md->flags;
497                                 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
498                                 data.mounted_uid = make_kuid(current_user_ns(), 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 = make_kuid(current_user_ns(), md->uid);
504                                 data.gid = make_kgid(current_user_ns(), md->gid);
505                                 data.file_mode = md->file_mode;
506                                 data.dir_mode = md->dir_mode;
507                                 data.info_fd = -1;
508                                 memcpy(data.mounted_vol, md->mounted_vol,
509                                         NCP_VOLNAME_LEN+1);
510                         }
511                         break;
512                 case NCP_MOUNT_VERSION_V4:
513                         {
514                                 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
515
516                                 data.flags = md->flags;
517                                 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
518                                 data.wdog_pid = find_get_pid(md->wdog_pid);
519                                 data.ncp_fd = md->ncp_fd;
520                                 data.time_out = md->time_out;
521                                 data.retry_count = md->retry_count;
522                                 data.uid = make_kuid(current_user_ns(), md->uid);
523                                 data.gid = make_kgid(current_user_ns(), md->gid);
524                                 data.file_mode = md->file_mode;
525                                 data.dir_mode = md->dir_mode;
526                                 data.info_fd = -1;
527                         }
528                         break;
529                 default:
530                         error = -ECHRNG;
531                         if (memcmp(raw_data, "vers", 4) == 0) {
532                                 error = ncp_parse_options(&data, raw_data);
533                         }
534                         if (error)
535                                 goto out;
536                         break;
537         }
538         error = -EINVAL;
539         if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
540             !gid_valid(data.gid))
541                 goto out;
542         error = -EBADF;
543         ncp_filp = fget(data.ncp_fd);
544         if (!ncp_filp)
545                 goto out;
546         error = -ENOTSOCK;
547         sock_inode = file_inode(ncp_filp);
548         if (!S_ISSOCK(sock_inode->i_mode))
549                 goto out_fput;
550         sock = SOCKET_I(sock_inode);
551         if (!sock)
552                 goto out_fput;
553                 
554         if (sock->type == SOCK_STREAM)
555                 default_bufsize = 0xF000;
556         else
557                 default_bufsize = 1024;
558
559         sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
560         sb->s_maxbytes = 0xFFFFFFFFU;
561         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
562         sb->s_blocksize_bits = 10;
563         sb->s_magic = NCP_SUPER_MAGIC;
564         sb->s_op = &ncp_sops;
565         sb->s_d_op = &ncp_dentry_operations;
566         sb->s_bdi = &server->bdi;
567
568         server = NCP_SBP(sb);
569         memset(server, 0, sizeof(*server));
570
571         error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
572         if (error)
573                 goto out_fput;
574
575         server->ncp_filp = ncp_filp;
576         server->ncp_sock = sock;
577         
578         if (data.info_fd != -1) {
579                 struct socket *info_sock;
580
581                 error = -EBADF;
582                 server->info_filp = fget(data.info_fd);
583                 if (!server->info_filp)
584                         goto out_bdi;
585                 error = -ENOTSOCK;
586                 sock_inode = file_inode(server->info_filp);
587                 if (!S_ISSOCK(sock_inode->i_mode))
588                         goto out_fput2;
589                 info_sock = SOCKET_I(sock_inode);
590                 if (!info_sock)
591                         goto out_fput2;
592                 error = -EBADFD;
593                 if (info_sock->type != SOCK_STREAM)
594                         goto out_fput2;
595                 server->info_sock = info_sock;
596         }
597
598 /*      server->lock = 0;       */
599         mutex_init(&server->mutex);
600         server->packet = NULL;
601 /*      server->buffer_size = 0;        */
602 /*      server->conn_status = 0;        */
603 /*      server->root_dentry = NULL;     */
604 /*      server->root_setuped = 0;       */
605         mutex_init(&server->root_setup_lock);
606 #ifdef CONFIG_NCPFS_PACKET_SIGNING
607 /*      server->sign_wanted = 0;        */
608 /*      server->sign_active = 0;        */
609 #endif
610         init_rwsem(&server->auth_rwsem);
611         server->auth.auth_type = NCP_AUTH_NONE;
612 /*      server->auth.object_name_len = 0;       */
613 /*      server->auth.object_name = NULL;        */
614 /*      server->auth.object_type = 0;           */
615 /*      server->priv.len = 0;                   */
616 /*      server->priv.data = NULL;               */
617
618         server->m = data;
619         /* Although anything producing this is buggy, it happens
620            now because of PATH_MAX changes.. */
621         if (server->m.time_out < 1) {
622                 server->m.time_out = 10;
623                 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
624         }
625         server->m.time_out = server->m.time_out * HZ / 100;
626         server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
627         server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
628
629 #ifdef CONFIG_NCPFS_NLS
630         /* load the default NLS charsets */
631         server->nls_vol = load_nls_default();
632         server->nls_io = load_nls_default();
633 #endif /* CONFIG_NCPFS_NLS */
634
635         atomic_set(&server->dentry_ttl, 0);     /* no caching */
636
637         INIT_LIST_HEAD(&server->tx.requests);
638         mutex_init(&server->rcv.creq_mutex);
639         server->tx.creq         = NULL;
640         server->rcv.creq        = NULL;
641
642         init_timer(&server->timeout_tm);
643 #undef NCP_PACKET_SIZE
644 #define NCP_PACKET_SIZE 131072
645         error = -ENOMEM;
646         server->packet_size = NCP_PACKET_SIZE;
647         server->packet = vmalloc(NCP_PACKET_SIZE);
648         if (server->packet == NULL)
649                 goto out_nls;
650         server->txbuf = vmalloc(NCP_PACKET_SIZE);
651         if (server->txbuf == NULL)
652                 goto out_packet;
653         server->rxbuf = vmalloc(NCP_PACKET_SIZE);
654         if (server->rxbuf == NULL)
655                 goto out_txbuf;
656
657         lock_sock(sock->sk);
658         server->data_ready      = sock->sk->sk_data_ready;
659         server->write_space     = sock->sk->sk_write_space;
660         server->error_report    = sock->sk->sk_error_report;
661         sock->sk->sk_user_data  = server;
662         sock->sk->sk_data_ready   = ncp_tcp_data_ready;
663         sock->sk->sk_error_report = ncp_tcp_error_report;
664         if (sock->type == SOCK_STREAM) {
665                 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
666                 server->rcv.len = 10;
667                 server->rcv.state = 0;
668                 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
669                 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
670                 sock->sk->sk_write_space = ncp_tcp_write_space;
671         } else {
672                 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
673                 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
674                 server->timeout_tm.data = (unsigned long)server;
675                 server->timeout_tm.function = ncpdgram_timeout_call;
676         }
677         release_sock(sock->sk);
678
679         ncp_lock_server(server);
680         error = ncp_connect(server);
681         ncp_unlock_server(server);
682         if (error < 0)
683                 goto out_rxbuf;
684         DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
685
686         error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
687 #ifdef CONFIG_NCPFS_PACKET_SIGNING
688         if (ncp_negotiate_size_and_options(server, default_bufsize,
689                 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
690         {
691                 if (options != NCP_DEFAULT_OPTIONS)
692                 {
693                         if (ncp_negotiate_size_and_options(server, 
694                                 default_bufsize,
695                                 options & 2, 
696                                 &(server->buffer_size), &options) != 0)
697                                 
698                         {
699                                 goto out_disconnect;
700                         }
701                 }
702                 ncp_lock_server(server);
703                 if (options & 2)
704                         server->sign_wanted = 1;
705                 ncp_unlock_server(server);
706         }
707         else 
708 #endif  /* CONFIG_NCPFS_PACKET_SIGNING */
709         if (ncp_negotiate_buffersize(server, default_bufsize,
710                                      &(server->buffer_size)) != 0)
711                 goto out_disconnect;
712         DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
713
714         memset(&finfo, 0, sizeof(finfo));
715         finfo.i.attributes      = aDIR;
716         finfo.i.dataStreamSize  = 0;    /* ignored */
717         finfo.i.dirEntNum       = 0;
718         finfo.i.DosDirNum       = 0;
719 #ifdef CONFIG_NCPFS_SMALLDOS
720         finfo.i.NSCreator       = NW_NS_DOS;
721 #endif
722         finfo.volume            = NCP_NUMBER_OF_VOLUMES;
723         /* set dates of mountpoint to Jan 1, 1986; 00:00 */
724         finfo.i.creationTime    = finfo.i.modifyTime
725                                 = cpu_to_le16(0x0000);
726         finfo.i.creationDate    = finfo.i.modifyDate
727                                 = finfo.i.lastAccessDate
728                                 = cpu_to_le16(0x0C21);
729         finfo.i.nameLen         = 0;
730         finfo.i.entryName[0]    = '\0';
731
732         finfo.opened            = 0;
733         finfo.ino               = 2;    /* tradition */
734
735         server->name_space[finfo.volume] = NW_NS_DOS;
736
737         error = -ENOMEM;
738         root_inode = ncp_iget(sb, &finfo);
739         if (!root_inode)
740                 goto out_disconnect;
741         DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
742         sb->s_root = d_make_root(root_inode);
743         if (!sb->s_root)
744                 goto out_disconnect;
745         return 0;
746
747 out_disconnect:
748         ncp_lock_server(server);
749         ncp_disconnect(server);
750         ncp_unlock_server(server);
751 out_rxbuf:
752         ncp_stop_tasks(server);
753         vfree(server->rxbuf);
754 out_txbuf:
755         vfree(server->txbuf);
756 out_packet:
757         vfree(server->packet);
758 out_nls:
759 #ifdef CONFIG_NCPFS_NLS
760         unload_nls(server->nls_io);
761         unload_nls(server->nls_vol);
762 #endif
763         mutex_destroy(&server->rcv.creq_mutex);
764         mutex_destroy(&server->root_setup_lock);
765         mutex_destroy(&server->mutex);
766 out_fput2:
767         if (server->info_filp)
768                 fput(server->info_filp);
769 out_bdi:
770         bdi_destroy(&server->bdi);
771 out_fput:
772         /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
773          * 
774          * The previously used put_filp(ncp_filp); was bogus, since
775          * it doesn't perform proper unlocking.
776          */
777         fput(ncp_filp);
778 out:
779         put_pid(data.wdog_pid);
780         sb->s_fs_info = NULL;
781         kfree(server);
782         return error;
783 }
784
785 static void ncp_put_super(struct super_block *sb)
786 {
787         struct ncp_server *server = NCP_SBP(sb);
788
789         ncp_lock_server(server);
790         ncp_disconnect(server);
791         ncp_unlock_server(server);
792
793         ncp_stop_tasks(server);
794
795 #ifdef CONFIG_NCPFS_NLS
796         /* unload the NLS charsets */
797         unload_nls(server->nls_vol);
798         unload_nls(server->nls_io);
799 #endif /* CONFIG_NCPFS_NLS */
800         mutex_destroy(&server->rcv.creq_mutex);
801         mutex_destroy(&server->root_setup_lock);
802         mutex_destroy(&server->mutex);
803
804         if (server->info_filp)
805                 fput(server->info_filp);
806         fput(server->ncp_filp);
807         kill_pid(server->m.wdog_pid, SIGTERM, 1);
808         put_pid(server->m.wdog_pid);
809
810         bdi_destroy(&server->bdi);
811         kfree(server->priv.data);
812         kfree(server->auth.object_name);
813         vfree(server->rxbuf);
814         vfree(server->txbuf);
815         vfree(server->packet);
816         sb->s_fs_info = NULL;
817         kfree(server);
818 }
819
820 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
821 {
822         struct dentry* d;
823         struct inode* i;
824         struct ncp_inode_info* ni;
825         struct ncp_server* s;
826         struct ncp_volume_info vi;
827         struct super_block *sb = dentry->d_sb;
828         int err;
829         __u8 dh;
830         
831         d = sb->s_root;
832         if (!d) {
833                 goto dflt;
834         }
835         i = d->d_inode;
836         if (!i) {
837                 goto dflt;
838         }
839         ni = NCP_FINFO(i);
840         if (!ni) {
841                 goto dflt;
842         }
843         s = NCP_SBP(sb);
844         if (!s) {
845                 goto dflt;
846         }
847         if (!s->m.mounted_vol[0]) {
848                 goto dflt;
849         }
850
851         err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
852         if (err) {
853                 goto dflt;
854         }
855         err = ncp_get_directory_info(s, dh, &vi);
856         ncp_dirhandle_free(s, dh);
857         if (err) {
858                 goto dflt;
859         }
860         buf->f_type = NCP_SUPER_MAGIC;
861         buf->f_bsize = vi.sectors_per_block * 512;
862         buf->f_blocks = vi.total_blocks;
863         buf->f_bfree = vi.free_blocks;
864         buf->f_bavail = vi.free_blocks;
865         buf->f_files = vi.total_dir_entries;
866         buf->f_ffree = vi.available_dir_entries;
867         buf->f_namelen = 12;
868         return 0;
869
870         /* We cannot say how much disk space is left on a mounted
871            NetWare Server, because free space is distributed over
872            volumes, and the current user might have disk quotas. So
873            free space is not that simple to determine. Our decision
874            here is to err conservatively. */
875
876 dflt:;
877         buf->f_type = NCP_SUPER_MAGIC;
878         buf->f_bsize = NCP_BLOCK_SIZE;
879         buf->f_blocks = 0;
880         buf->f_bfree = 0;
881         buf->f_bavail = 0;
882         buf->f_namelen = 12;
883         return 0;
884 }
885
886 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
887 {
888         struct inode *inode = dentry->d_inode;
889         int result = 0;
890         __le32 info_mask;
891         struct nw_modify_dos_info info;
892         struct ncp_server *server;
893
894         result = -EIO;
895
896         server = NCP_SERVER(inode);
897         if (!server)    /* How this could happen? */
898                 goto out;
899
900         result = -EPERM;
901         if (IS_DEADDIR(dentry->d_inode))
902                 goto out;
903
904         /* ageing the dentry to force validation */
905         ncp_age_dentry(server, dentry);
906
907         result = inode_change_ok(inode, attr);
908         if (result < 0)
909                 goto out;
910
911         result = -EPERM;
912         if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
913                 goto out;
914
915         if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
916                 goto out;
917
918         if (((attr->ia_valid & ATTR_MODE) &&
919              (attr->ia_mode &
920               ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
921                 goto out;
922
923         info_mask = 0;
924         memset(&info, 0, sizeof(info));
925
926 #if 1 
927         if ((attr->ia_valid & ATTR_MODE) != 0)
928         {
929                 umode_t newmode = attr->ia_mode;
930
931                 info_mask |= DM_ATTRIBUTES;
932
933                 if (S_ISDIR(inode->i_mode)) {
934                         newmode &= server->m.dir_mode;
935                 } else {
936 #ifdef CONFIG_NCPFS_EXTRAS                      
937                         if (server->m.flags & NCP_MOUNT_EXTRAS) {
938                                 /* any non-default execute bit set */
939                                 if (newmode & ~server->m.file_mode & S_IXUGO)
940                                         info.attributes |= aSHARED | aSYSTEM;
941                                 /* read for group/world and not in default file_mode */
942                                 else if (newmode & ~server->m.file_mode & S_IRUGO)
943                                         info.attributes |= aSHARED;
944                         } else
945 #endif
946                                 newmode &= server->m.file_mode;                 
947                 }
948                 if (newmode & S_IWUGO)
949                         info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
950                 else
951                         info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
952
953 #ifdef CONFIG_NCPFS_NFS_NS
954                 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
955                         result = ncp_modify_nfs_info(server,
956                                                      NCP_FINFO(inode)->volNumber,
957                                                      NCP_FINFO(inode)->dirEntNum,
958                                                      attr->ia_mode, 0);
959                         if (result != 0)
960                                 goto out;
961                         info.attributes &= ~(aSHARED | aSYSTEM);
962                         {
963                                 /* mark partial success */
964                                 struct iattr tmpattr;
965                                 
966                                 tmpattr.ia_valid = ATTR_MODE;
967                                 tmpattr.ia_mode = attr->ia_mode;
968
969                                 setattr_copy(inode, &tmpattr);
970                                 mark_inode_dirty(inode);
971                         }
972                 }
973 #endif
974         }
975 #endif
976
977         /* Do SIZE before attributes, otherwise mtime together with size does not work...
978          */
979         if ((attr->ia_valid & ATTR_SIZE) != 0) {
980                 int written;
981
982                 DPRINTK("ncpfs: trying to change size to %ld\n",
983                         attr->ia_size);
984
985                 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
986                         result = -EACCES;
987                         goto out;
988                 }
989                 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
990                           attr->ia_size, 0, "", &written);
991
992                 /* According to ndir, the changes only take effect after
993                    closing the file */
994                 ncp_inode_close(inode);
995                 result = ncp_make_closed(inode);
996                 if (result)
997                         goto out;
998
999                 if (attr->ia_size != i_size_read(inode)) {
1000                         truncate_setsize(inode, attr->ia_size);
1001                         mark_inode_dirty(inode);
1002                 }
1003         }
1004         if ((attr->ia_valid & ATTR_CTIME) != 0) {
1005                 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
1006                 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
1007                              &info.creationTime, &info.creationDate);
1008         }
1009         if ((attr->ia_valid & ATTR_MTIME) != 0) {
1010                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
1011                 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
1012                                   &info.modifyTime, &info.modifyDate);
1013         }
1014         if ((attr->ia_valid & ATTR_ATIME) != 0) {
1015                 __le16 dummy;
1016                 info_mask |= (DM_LAST_ACCESS_DATE);
1017                 ncp_date_unix2dos(attr->ia_atime.tv_sec,
1018                                   &dummy, &info.lastAccessDate);
1019         }
1020         if (info_mask != 0) {
1021                 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1022                                       inode, info_mask, &info);
1023                 if (result != 0) {
1024                         if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1025                                 /* NetWare seems not to allow this. I
1026                                    do not know why. So, just tell the
1027                                    user everything went fine. This is
1028                                    a terrible hack, but I do not know
1029                                    how to do this correctly. */
1030                                 result = 0;
1031                         } else
1032                                 goto out;
1033                 }
1034 #ifdef CONFIG_NCPFS_STRONG              
1035                 if ((!result) && (info_mask & DM_ATTRIBUTES))
1036                         NCP_FINFO(inode)->nwattr = info.attributes;
1037 #endif
1038         }
1039         if (result)
1040                 goto out;
1041
1042         setattr_copy(inode, attr);
1043         mark_inode_dirty(inode);
1044
1045 out:
1046         if (result > 0)
1047                 result = -EACCES;
1048         return result;
1049 }
1050
1051 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1052         int flags, const char *dev_name, void *data)
1053 {
1054         return mount_nodev(fs_type, flags, data, ncp_fill_super);
1055 }
1056
1057 static struct file_system_type ncp_fs_type = {
1058         .owner          = THIS_MODULE,
1059         .name           = "ncpfs",
1060         .mount          = ncp_mount,
1061         .kill_sb        = kill_anon_super,
1062         .fs_flags       = FS_BINARY_MOUNTDATA,
1063 };
1064 MODULE_ALIAS_FS("ncpfs");
1065
1066 static int __init init_ncp_fs(void)
1067 {
1068         int err;
1069         DPRINTK("ncpfs: init_ncp_fs called\n");
1070
1071         err = init_inodecache();
1072         if (err)
1073                 goto out1;
1074         err = register_filesystem(&ncp_fs_type);
1075         if (err)
1076                 goto out;
1077         return 0;
1078 out:
1079         destroy_inodecache();
1080 out1:
1081         return err;
1082 }
1083
1084 static void __exit exit_ncp_fs(void)
1085 {
1086         DPRINTK("ncpfs: exit_ncp_fs called\n");
1087         unregister_filesystem(&ncp_fs_type);
1088         destroy_inodecache();
1089 }
1090
1091 module_init(init_ncp_fs)
1092 module_exit(exit_ncp_fs)
1093 MODULE_LICENSE("GPL");