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