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