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