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