]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/ncpfs/inode.c
Merge branch 'for-next' of git://git.infradead.org/users/eparis/notify
[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 #include <linux/module.h>
13
14 #include <asm/uaccess.h>
15 #include <asm/byteorder.h>
16
17 #include <linux/time.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/string.h>
21 #include <linux/stat.h>
22 #include <linux/errno.h>
23 #include <linux/file.h>
24 #include <linux/fcntl.h>
25 #include <linux/slab.h>
26 #include <linux/vmalloc.h>
27 #include <linux/init.h>
28 #include <linux/vfs.h>
29 #include <linux/mount.h>
30 #include <linux/seq_file.h>
31 #include <linux/namei.h>
32
33 #include <net/sock.h>
34
35 #include "ncp_fs.h"
36 #include "getopt.h"
37
38 #define NCP_DEFAULT_FILE_MODE 0600
39 #define NCP_DEFAULT_DIR_MODE 0700
40 #define NCP_DEFAULT_TIME_OUT 10
41 #define NCP_DEFAULT_RETRY_COUNT 20
42
43 static void ncp_evict_inode(struct inode *);
44 static void ncp_put_super(struct super_block *);
45 static int  ncp_statfs(struct dentry *, struct kstatfs *);
46 static int  ncp_show_options(struct seq_file *, struct dentry *);
47
48 static struct kmem_cache * ncp_inode_cachep;
49
50 static struct inode *ncp_alloc_inode(struct super_block *sb)
51 {
52         struct ncp_inode_info *ei;
53         ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
54         if (!ei)
55                 return NULL;
56         return &ei->vfs_inode;
57 }
58
59 static void ncp_i_callback(struct rcu_head *head)
60 {
61         struct inode *inode = container_of(head, struct inode, i_rcu);
62         kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
63 }
64
65 static void ncp_destroy_inode(struct inode *inode)
66 {
67         call_rcu(&inode->i_rcu, ncp_i_callback);
68 }
69
70 static void init_once(void *foo)
71 {
72         struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
73
74         mutex_init(&ei->open_mutex);
75         inode_init_once(&ei->vfs_inode);
76 }
77
78 static int init_inodecache(void)
79 {
80         ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
81                                              sizeof(struct ncp_inode_info),
82                                              0, (SLAB_RECLAIM_ACCOUNT|
83                                                 SLAB_MEM_SPREAD),
84                                              init_once);
85         if (ncp_inode_cachep == NULL)
86                 return -ENOMEM;
87         return 0;
88 }
89
90 static void destroy_inodecache(void)
91 {
92         /*
93          * Make sure all delayed rcu free inodes are flushed before we
94          * destroy cache.
95          */
96         rcu_barrier();
97         kmem_cache_destroy(ncp_inode_cachep);
98 }
99
100 static int ncp_remount(struct super_block *sb, int *flags, char* data)
101 {
102         *flags |= MS_NODIRATIME;
103         return 0;
104 }
105
106 static const struct super_operations ncp_sops =
107 {
108         .alloc_inode    = ncp_alloc_inode,
109         .destroy_inode  = ncp_destroy_inode,
110         .drop_inode     = generic_delete_inode,
111         .evict_inode    = ncp_evict_inode,
112         .put_super      = ncp_put_super,
113         .statfs         = ncp_statfs,
114         .remount_fs     = ncp_remount,
115         .show_options   = ncp_show_options,
116 };
117
118 /*
119  * Fill in the ncpfs-specific information in the inode.
120  */
121 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
122 {
123         NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
124         NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
125         NCP_FINFO(inode)->volNumber = nwinfo->volume;
126 }
127
128 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
129 {
130         ncp_update_dirent(inode, nwinfo);
131         NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
132         NCP_FINFO(inode)->access = nwinfo->access;
133         memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
134                         sizeof(nwinfo->file_handle));
135         DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
136                 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
137                 NCP_FINFO(inode)->dirEntNum);
138 }
139
140 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
141 {
142         /* NFS namespace mode overrides others if it's set. */
143         DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
144                 nwi->entryName, nwi->nfs.mode);
145         if (nwi->nfs.mode) {
146                 /* XXX Security? */
147                 inode->i_mode = nwi->nfs.mode;
148         }
149
150         inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
151
152         inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
153         inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
154         inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
155         inode->i_atime.tv_nsec = 0;
156         inode->i_mtime.tv_nsec = 0;
157         inode->i_ctime.tv_nsec = 0;
158 }
159
160 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
161 {
162         struct nw_info_struct *nwi = &nwinfo->i;
163         struct ncp_server *server = NCP_SERVER(inode);
164
165         if (nwi->attributes & aDIR) {
166                 inode->i_mode = server->m.dir_mode;
167                 /* for directories dataStreamSize seems to be some
168                    Object ID ??? */
169                 i_size_write(inode, NCP_BLOCK_SIZE);
170         } else {
171                 u32 size;
172
173                 inode->i_mode = server->m.file_mode;
174                 size = le32_to_cpu(nwi->dataStreamSize);
175                 i_size_write(inode, size);
176 #ifdef CONFIG_NCPFS_EXTRAS
177                 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
178                  && (nwi->attributes & aSHARED)) {
179                         switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
180                                 case aHIDDEN:
181                                         if (server->m.flags & NCP_MOUNT_SYMLINKS) {
182                                                 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
183                                                  && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
184                                                         inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
185                                                         NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
186                                                         break;
187                                                 }
188                                         }
189                                         /* FALLTHROUGH */
190                                 case 0:
191                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
192                                                 inode->i_mode |= S_IRUGO;
193                                         break;
194                                 case aSYSTEM:
195                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
196                                                 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
197                                         break;
198                                 /* case aSYSTEM|aHIDDEN: */
199                                 default:
200                                         /* reserved combination */
201                                         break;
202                         }
203                 }
204 #endif
205         }
206         if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
207 }
208
209 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
210 {
211         NCP_FINFO(inode)->flags = 0;
212         if (!atomic_read(&NCP_FINFO(inode)->opened)) {
213                 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
214                 ncp_update_attrs(inode, nwinfo);
215         }
216
217         ncp_update_dates(inode, &nwinfo->i);
218         ncp_update_dirent(inode, nwinfo);
219 }
220
221 /*
222  * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
223  */
224 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
225 {
226         struct ncp_server *server = NCP_SERVER(inode);
227
228         NCP_FINFO(inode)->flags = 0;
229         
230         ncp_update_attrs(inode, nwinfo);
231
232         DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
233
234         set_nlink(inode, 1);
235         inode->i_uid = server->m.uid;
236         inode->i_gid = server->m.gid;
237
238         ncp_update_dates(inode, &nwinfo->i);
239         ncp_update_inode(inode, nwinfo);
240 }
241
242 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
243 static const struct inode_operations ncp_symlink_inode_operations = {
244         .readlink       = generic_readlink,
245         .follow_link    = page_follow_link_light,
246         .put_link       = page_put_link,
247         .setattr        = ncp_notify_change,
248 };
249 #endif
250
251 /*
252  * Get a new inode.
253  */
254 struct inode * 
255 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
256 {
257         struct inode *inode;
258
259         if (info == NULL) {
260                 printk(KERN_ERR "ncp_iget: info is NULL\n");
261                 return NULL;
262         }
263
264         inode = new_inode(sb);
265         if (inode) {
266                 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
267
268                 inode->i_mapping->backing_dev_info = sb->s_bdi;
269                 inode->i_ino = info->ino;
270                 ncp_set_attr(inode, info);
271                 if (S_ISREG(inode->i_mode)) {
272                         inode->i_op = &ncp_file_inode_operations;
273                         inode->i_fop = &ncp_file_operations;
274                 } else if (S_ISDIR(inode->i_mode)) {
275                         inode->i_op = &ncp_dir_inode_operations;
276                         inode->i_fop = &ncp_dir_operations;
277 #ifdef CONFIG_NCPFS_NFS_NS
278                 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
279                         init_special_inode(inode, inode->i_mode,
280                                 new_decode_dev(info->i.nfs.rdev));
281 #endif
282 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
283                 } else if (S_ISLNK(inode->i_mode)) {
284                         inode->i_op = &ncp_symlink_inode_operations;
285                         inode->i_data.a_ops = &ncp_symlink_aops;
286 #endif
287                 } else {
288                         make_bad_inode(inode);
289                 }
290                 insert_inode_hash(inode);
291         } else
292                 printk(KERN_ERR "ncp_iget: iget failed!\n");
293         return inode;
294 }
295
296 static void
297 ncp_evict_inode(struct inode *inode)
298 {
299         truncate_inode_pages(&inode->i_data, 0);
300         clear_inode(inode);
301
302         if (S_ISDIR(inode->i_mode)) {
303                 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
304         }
305
306         if (ncp_make_closed(inode) != 0) {
307                 /* We can't do anything but complain. */
308                 printk(KERN_ERR "ncp_evict_inode: could not close\n");
309         }
310 }
311
312 static void ncp_stop_tasks(struct ncp_server *server) {
313         struct sock* sk = server->ncp_sock->sk;
314
315         lock_sock(sk);
316         sk->sk_error_report = server->error_report;
317         sk->sk_data_ready   = server->data_ready;
318         sk->sk_write_space  = server->write_space;
319         release_sock(sk);
320         del_timer_sync(&server->timeout_tm);
321
322         flush_work(&server->rcv.tq);
323         if (sk->sk_socket->type == SOCK_STREAM)
324                 flush_work(&server->tx.tq);
325         else
326                 flush_work(&server->timeout_tq);
327 }
328
329 static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
330 {
331         struct ncp_server *server = NCP_SBP(root->d_sb);
332         unsigned int tmp;
333
334         if (server->m.uid != 0)
335                 seq_printf(seq, ",uid=%u", server->m.uid);
336         if (server->m.gid != 0)
337                 seq_printf(seq, ",gid=%u", server->m.gid);
338         if (server->m.mounted_uid != 0)
339                 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
340         tmp = server->m.file_mode & S_IALLUGO;
341         if (tmp != NCP_DEFAULT_FILE_MODE)
342                 seq_printf(seq, ",mode=0%o", tmp);
343         tmp = server->m.dir_mode & S_IALLUGO;
344         if (tmp != NCP_DEFAULT_DIR_MODE)
345                 seq_printf(seq, ",dirmode=0%o", tmp);
346         if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
347                 tmp = server->m.time_out * 100 / HZ;
348                 seq_printf(seq, ",timeout=%u", tmp);
349         }
350         if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
351                 seq_printf(seq, ",retry=%u", server->m.retry_count);
352         if (server->m.flags != 0)
353                 seq_printf(seq, ",flags=%lu", server->m.flags);
354         if (server->m.wdog_pid != NULL)
355                 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
356
357         return 0;
358 }
359
360 static const struct ncp_option ncp_opts[] = {
361         { "uid",        OPT_INT,        'u' },
362         { "gid",        OPT_INT,        'g' },
363         { "owner",      OPT_INT,        'o' },
364         { "mode",       OPT_INT,        'm' },
365         { "dirmode",    OPT_INT,        'd' },
366         { "timeout",    OPT_INT,        't' },
367         { "retry",      OPT_INT,        'r' },
368         { "flags",      OPT_INT,        'f' },
369         { "wdogpid",    OPT_INT,        'w' },
370         { "ncpfd",      OPT_INT,        'n' },
371         { "infofd",     OPT_INT,        'i' },  /* v5 */
372         { "version",    OPT_INT,        'v' },
373         { NULL,         0,              0 } };
374
375 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
376         int optval;
377         char *optarg;
378         unsigned long optint;
379         int version = 0;
380         int ret;
381
382         data->flags = 0;
383         data->int_flags = 0;
384         data->mounted_uid = 0;
385         data->wdog_pid = NULL;
386         data->ncp_fd = ~0;
387         data->time_out = NCP_DEFAULT_TIME_OUT;
388         data->retry_count = NCP_DEFAULT_RETRY_COUNT;
389         data->uid = 0;
390         data->gid = 0;
391         data->file_mode = NCP_DEFAULT_FILE_MODE;
392         data->dir_mode = NCP_DEFAULT_DIR_MODE;
393         data->info_fd = -1;
394         data->mounted_vol[0] = 0;
395         
396         while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
397                 ret = optval;
398                 if (ret < 0)
399                         goto err;
400                 switch (optval) {
401                         case 'u':
402                                 data->uid = optint;
403                                 break;
404                         case 'g':
405                                 data->gid = optint;
406                                 break;
407                         case 'o':
408                                 data->mounted_uid = optint;
409                                 break;
410                         case 'm':
411                                 data->file_mode = optint;
412                                 break;
413                         case 'd':
414                                 data->dir_mode = optint;
415                                 break;
416                         case 't':
417                                 data->time_out = optint;
418                                 break;
419                         case 'r':
420                                 data->retry_count = optint;
421                                 break;
422                         case 'f':
423                                 data->flags = optint;
424                                 break;
425                         case 'w':
426                                 data->wdog_pid = find_get_pid(optint);
427                                 break;
428                         case 'n':
429                                 data->ncp_fd = optint;
430                                 break;
431                         case 'i':
432                                 data->info_fd = optint;
433                                 break;
434                         case 'v':
435                                 ret = -ECHRNG;
436                                 if (optint < NCP_MOUNT_VERSION_V4)
437                                         goto err;
438                                 if (optint > NCP_MOUNT_VERSION_V5)
439                                         goto err;
440                                 version = optint;
441                                 break;
442                         
443                 }
444         }
445         return 0;
446 err:
447         put_pid(data->wdog_pid);
448         data->wdog_pid = NULL;
449         return ret;
450 }
451
452 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
453 {
454         struct ncp_mount_data_kernel data;
455         struct ncp_server *server;
456         struct file *ncp_filp;
457         struct inode *root_inode;
458         struct inode *sock_inode;
459         struct socket *sock;
460         int error;
461         int default_bufsize;
462 #ifdef CONFIG_NCPFS_PACKET_SIGNING
463         int options;
464 #endif
465         struct ncp_entry_info finfo;
466
467         memset(&data, 0, sizeof(data));
468         server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
469         if (!server)
470                 return -ENOMEM;
471         sb->s_fs_info = server;
472
473         error = -EFAULT;
474         if (raw_data == NULL)
475                 goto out;
476         switch (*(int*)raw_data) {
477                 case NCP_MOUNT_VERSION:
478                         {
479                                 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
480
481                                 data.flags = md->flags;
482                                 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
483                                 data.mounted_uid = md->mounted_uid;
484                                 data.wdog_pid = find_get_pid(md->wdog_pid);
485                                 data.ncp_fd = md->ncp_fd;
486                                 data.time_out = md->time_out;
487                                 data.retry_count = md->retry_count;
488                                 data.uid = md->uid;
489                                 data.gid = md->gid;
490                                 data.file_mode = md->file_mode;
491                                 data.dir_mode = md->dir_mode;
492                                 data.info_fd = -1;
493                                 memcpy(data.mounted_vol, md->mounted_vol,
494                                         NCP_VOLNAME_LEN+1);
495                         }
496                         break;
497                 case NCP_MOUNT_VERSION_V4:
498                         {
499                                 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
500
501                                 data.flags = md->flags;
502                                 data.mounted_uid = md->mounted_uid;
503                                 data.wdog_pid = find_get_pid(md->wdog_pid);
504                                 data.ncp_fd = md->ncp_fd;
505                                 data.time_out = md->time_out;
506                                 data.retry_count = md->retry_count;
507                                 data.uid = md->uid;
508                                 data.gid = md->gid;
509                                 data.file_mode = md->file_mode;
510                                 data.dir_mode = md->dir_mode;
511                                 data.info_fd = -1;
512                         }
513                         break;
514                 default:
515                         error = -ECHRNG;
516                         if (memcmp(raw_data, "vers", 4) == 0) {
517                                 error = ncp_parse_options(&data, raw_data);
518                         }
519                         if (error)
520                                 goto out;
521                         break;
522         }
523         error = -EBADF;
524         ncp_filp = fget(data.ncp_fd);
525         if (!ncp_filp)
526                 goto out;
527         error = -ENOTSOCK;
528         sock_inode = ncp_filp->f_path.dentry->d_inode;
529         if (!S_ISSOCK(sock_inode->i_mode))
530                 goto out_fput;
531         sock = SOCKET_I(sock_inode);
532         if (!sock)
533                 goto out_fput;
534                 
535         if (sock->type == SOCK_STREAM)
536                 default_bufsize = 0xF000;
537         else
538                 default_bufsize = 1024;
539
540         sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
541         sb->s_maxbytes = 0xFFFFFFFFU;
542         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
543         sb->s_blocksize_bits = 10;
544         sb->s_magic = NCP_SUPER_MAGIC;
545         sb->s_op = &ncp_sops;
546         sb->s_d_op = &ncp_dentry_operations;
547         sb->s_bdi = &server->bdi;
548
549         server = NCP_SBP(sb);
550         memset(server, 0, sizeof(*server));
551
552         error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
553         if (error)
554                 goto out_fput;
555
556         server->ncp_filp = ncp_filp;
557         server->ncp_sock = sock;
558         
559         if (data.info_fd != -1) {
560                 struct socket *info_sock;
561
562                 error = -EBADF;
563                 server->info_filp = fget(data.info_fd);
564                 if (!server->info_filp)
565                         goto out_bdi;
566                 error = -ENOTSOCK;
567                 sock_inode = server->info_filp->f_path.dentry->d_inode;
568                 if (!S_ISSOCK(sock_inode->i_mode))
569                         goto out_fput2;
570                 info_sock = SOCKET_I(sock_inode);
571                 if (!info_sock)
572                         goto out_fput2;
573                 error = -EBADFD;
574                 if (info_sock->type != SOCK_STREAM)
575                         goto out_fput2;
576                 server->info_sock = info_sock;
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                 printk(KERN_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         DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) 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         DPRINTK("ncpfs: 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         DPRINTK("ncp_fill_super: 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_filp)
749                 fput(server->info_filp);
750 out_bdi:
751         bdi_destroy(&server->bdi);
752 out_fput:
753         /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
754          * 
755          * The previously used put_filp(ncp_filp); was bogus, since
756          * it doesn't perform proper unlocking.
757          */
758         fput(ncp_filp);
759 out:
760         put_pid(data.wdog_pid);
761         sb->s_fs_info = NULL;
762         kfree(server);
763         return error;
764 }
765
766 static void ncp_put_super(struct super_block *sb)
767 {
768         struct ncp_server *server = NCP_SBP(sb);
769
770         ncp_lock_server(server);
771         ncp_disconnect(server);
772         ncp_unlock_server(server);
773
774         ncp_stop_tasks(server);
775
776 #ifdef CONFIG_NCPFS_NLS
777         /* unload the NLS charsets */
778         unload_nls(server->nls_vol);
779         unload_nls(server->nls_io);
780 #endif /* CONFIG_NCPFS_NLS */
781         mutex_destroy(&server->rcv.creq_mutex);
782         mutex_destroy(&server->root_setup_lock);
783         mutex_destroy(&server->mutex);
784
785         if (server->info_filp)
786                 fput(server->info_filp);
787         fput(server->ncp_filp);
788         kill_pid(server->m.wdog_pid, SIGTERM, 1);
789         put_pid(server->m.wdog_pid);
790
791         bdi_destroy(&server->bdi);
792         kfree(server->priv.data);
793         kfree(server->auth.object_name);
794         vfree(server->rxbuf);
795         vfree(server->txbuf);
796         vfree(server->packet);
797         sb->s_fs_info = NULL;
798         kfree(server);
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         /* ageing the dentry to force validation */
882         ncp_age_dentry(server, dentry);
883
884         result = inode_change_ok(inode, attr);
885         if (result < 0)
886                 goto out;
887
888         result = -EPERM;
889         if (((attr->ia_valid & ATTR_UID) &&
890              (attr->ia_uid != server->m.uid)))
891                 goto out;
892
893         if (((attr->ia_valid & ATTR_GID) &&
894              (attr->ia_gid != server->m.gid)))
895                 goto out;
896
897         if (((attr->ia_valid & ATTR_MODE) &&
898              (attr->ia_mode &
899               ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
900                 goto out;
901
902         info_mask = 0;
903         memset(&info, 0, sizeof(info));
904
905 #if 1 
906         if ((attr->ia_valid & ATTR_MODE) != 0)
907         {
908                 umode_t newmode = attr->ia_mode;
909
910                 info_mask |= DM_ATTRIBUTES;
911
912                 if (S_ISDIR(inode->i_mode)) {
913                         newmode &= server->m.dir_mode;
914                 } else {
915 #ifdef CONFIG_NCPFS_EXTRAS                      
916                         if (server->m.flags & NCP_MOUNT_EXTRAS) {
917                                 /* any non-default execute bit set */
918                                 if (newmode & ~server->m.file_mode & S_IXUGO)
919                                         info.attributes |= aSHARED | aSYSTEM;
920                                 /* read for group/world and not in default file_mode */
921                                 else if (newmode & ~server->m.file_mode & S_IRUGO)
922                                         info.attributes |= aSHARED;
923                         } else
924 #endif
925                                 newmode &= server->m.file_mode;                 
926                 }
927                 if (newmode & S_IWUGO)
928                         info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
929                 else
930                         info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
931
932 #ifdef CONFIG_NCPFS_NFS_NS
933                 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
934                         result = ncp_modify_nfs_info(server,
935                                                      NCP_FINFO(inode)->volNumber,
936                                                      NCP_FINFO(inode)->dirEntNum,
937                                                      attr->ia_mode, 0);
938                         if (result != 0)
939                                 goto out;
940                         info.attributes &= ~(aSHARED | aSYSTEM);
941                         {
942                                 /* mark partial success */
943                                 struct iattr tmpattr;
944                                 
945                                 tmpattr.ia_valid = ATTR_MODE;
946                                 tmpattr.ia_mode = attr->ia_mode;
947
948                                 setattr_copy(inode, &tmpattr);
949                                 mark_inode_dirty(inode);
950                         }
951                 }
952 #endif
953         }
954 #endif
955
956         /* Do SIZE before attributes, otherwise mtime together with size does not work...
957          */
958         if ((attr->ia_valid & ATTR_SIZE) != 0) {
959                 int written;
960
961                 DPRINTK("ncpfs: trying to change size to %ld\n",
962                         attr->ia_size);
963
964                 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
965                         result = -EACCES;
966                         goto out;
967                 }
968                 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
969                           attr->ia_size, 0, "", &written);
970
971                 /* According to ndir, the changes only take effect after
972                    closing the file */
973                 ncp_inode_close(inode);
974                 result = ncp_make_closed(inode);
975                 if (result)
976                         goto out;
977
978                 if (attr->ia_size != i_size_read(inode)) {
979                         truncate_setsize(inode, attr->ia_size);
980                         mark_inode_dirty(inode);
981                 }
982         }
983         if ((attr->ia_valid & ATTR_CTIME) != 0) {
984                 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
985                 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
986                              &info.creationTime, &info.creationDate);
987         }
988         if ((attr->ia_valid & ATTR_MTIME) != 0) {
989                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
990                 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
991                                   &info.modifyTime, &info.modifyDate);
992         }
993         if ((attr->ia_valid & ATTR_ATIME) != 0) {
994                 __le16 dummy;
995                 info_mask |= (DM_LAST_ACCESS_DATE);
996                 ncp_date_unix2dos(attr->ia_atime.tv_sec,
997                                   &dummy, &info.lastAccessDate);
998         }
999         if (info_mask != 0) {
1000                 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1001                                       inode, info_mask, &info);
1002                 if (result != 0) {
1003                         if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1004                                 /* NetWare seems not to allow this. I
1005                                    do not know why. So, just tell the
1006                                    user everything went fine. This is
1007                                    a terrible hack, but I do not know
1008                                    how to do this correctly. */
1009                                 result = 0;
1010                         } else
1011                                 goto out;
1012                 }
1013 #ifdef CONFIG_NCPFS_STRONG              
1014                 if ((!result) && (info_mask & DM_ATTRIBUTES))
1015                         NCP_FINFO(inode)->nwattr = info.attributes;
1016 #endif
1017         }
1018         if (result)
1019                 goto out;
1020
1021         setattr_copy(inode, attr);
1022         mark_inode_dirty(inode);
1023
1024 out:
1025         if (result > 0)
1026                 result = -EACCES;
1027         return result;
1028 }
1029
1030 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1031         int flags, const char *dev_name, void *data)
1032 {
1033         return mount_nodev(fs_type, flags, data, ncp_fill_super);
1034 }
1035
1036 static struct file_system_type ncp_fs_type = {
1037         .owner          = THIS_MODULE,
1038         .name           = "ncpfs",
1039         .mount          = ncp_mount,
1040         .kill_sb        = kill_anon_super,
1041         .fs_flags       = FS_BINARY_MOUNTDATA,
1042 };
1043
1044 static int __init init_ncp_fs(void)
1045 {
1046         int err;
1047         DPRINTK("ncpfs: init_ncp_fs called\n");
1048
1049         err = init_inodecache();
1050         if (err)
1051                 goto out1;
1052         err = register_filesystem(&ncp_fs_type);
1053         if (err)
1054                 goto out;
1055         return 0;
1056 out:
1057         destroy_inodecache();
1058 out1:
1059         return err;
1060 }
1061
1062 static void __exit exit_ncp_fs(void)
1063 {
1064         DPRINTK("ncpfs: exit_ncp_fs called\n");
1065         unregister_filesystem(&ncp_fs_type);
1066         destroy_inodecache();
1067 }
1068
1069 module_init(init_ncp_fs)
1070 module_exit(exit_ncp_fs)
1071 MODULE_LICENSE("GPL");