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