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