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