]> Pileus Git - ~andy/linux/blob - fs/ncpfs/inode.c
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
[~andy/linux] / fs / ncpfs / inode.c
1 /*
2  *  inode.c
3  *
4  *  Copyright (C) 1995, 1996 by Volker Lendecke
5  *  Modified for big endian by J.F. Chadima and David S. Miller
6  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7  *  Modified 1998 Wolfram Pienkoss for NLS
8  *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
9  *
10  */
11
12 #include <linux/module.h>
13
14 #include <asm/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
17
18 #include <linux/time.h>
19 #include <linux/kernel.h>
20 #include <linux/mm.h>
21 #include <linux/string.h>
22 #include <linux/stat.h>
23 #include <linux/errno.h>
24 #include <linux/file.h>
25 #include <linux/fcntl.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/init.h>
29 #include <linux/vfs.h>
30 #include <linux/mount.h>
31 #include <linux/seq_file.h>
32 #include <linux/namei.h>
33
34 #include <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_i_callback(struct rcu_head *head)
63 {
64         struct inode *inode = container_of(head, struct inode, i_rcu);
65         INIT_LIST_HEAD(&inode->i_dentry);
66         kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
67 }
68
69 static void ncp_destroy_inode(struct inode *inode)
70 {
71         call_rcu(&inode->i_rcu, ncp_i_callback);
72 }
73
74 static void init_once(void *foo)
75 {
76         struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
77
78         mutex_init(&ei->open_mutex);
79         inode_init_once(&ei->vfs_inode);
80 }
81
82 static int init_inodecache(void)
83 {
84         ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
85                                              sizeof(struct ncp_inode_info),
86                                              0, (SLAB_RECLAIM_ACCOUNT|
87                                                 SLAB_MEM_SPREAD),
88                                              init_once);
89         if (ncp_inode_cachep == NULL)
90                 return -ENOMEM;
91         return 0;
92 }
93
94 static void destroy_inodecache(void)
95 {
96         kmem_cache_destroy(ncp_inode_cachep);
97 }
98
99 static int ncp_remount(struct super_block *sb, int *flags, char* data)
100 {
101         *flags |= MS_NODIRATIME;
102         return 0;
103 }
104
105 static const struct super_operations ncp_sops =
106 {
107         .alloc_inode    = ncp_alloc_inode,
108         .destroy_inode  = ncp_destroy_inode,
109         .drop_inode     = generic_delete_inode,
110         .evict_inode    = ncp_evict_inode,
111         .put_super      = ncp_put_super,
112         .statfs         = ncp_statfs,
113         .remount_fs     = ncp_remount,
114         .show_options   = ncp_show_options,
115 };
116
117 /*
118  * Fill in the ncpfs-specific information in the inode.
119  */
120 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
121 {
122         NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
123         NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
124         NCP_FINFO(inode)->volNumber = nwinfo->volume;
125 }
126
127 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
128 {
129         ncp_update_dirent(inode, nwinfo);
130         NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
131         NCP_FINFO(inode)->access = nwinfo->access;
132         memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
133                         sizeof(nwinfo->file_handle));
134         DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
135                 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
136                 NCP_FINFO(inode)->dirEntNum);
137 }
138
139 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
140 {
141         /* NFS namespace mode overrides others if it's set. */
142         DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
143                 nwi->entryName, nwi->nfs.mode);
144         if (nwi->nfs.mode) {
145                 /* XXX Security? */
146                 inode->i_mode = nwi->nfs.mode;
147         }
148
149         inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
150
151         inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
152         inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
153         inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
154         inode->i_atime.tv_nsec = 0;
155         inode->i_mtime.tv_nsec = 0;
156         inode->i_ctime.tv_nsec = 0;
157 }
158
159 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
160 {
161         struct nw_info_struct *nwi = &nwinfo->i;
162         struct ncp_server *server = NCP_SERVER(inode);
163
164         if (nwi->attributes & aDIR) {
165                 inode->i_mode = server->m.dir_mode;
166                 /* for directories dataStreamSize seems to be some
167                    Object ID ??? */
168                 i_size_write(inode, NCP_BLOCK_SIZE);
169         } else {
170                 u32 size;
171
172                 inode->i_mode = server->m.file_mode;
173                 size = le32_to_cpu(nwi->dataStreamSize);
174                 i_size_write(inode, size);
175 #ifdef CONFIG_NCPFS_EXTRAS
176                 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
177                  && (nwi->attributes & aSHARED)) {
178                         switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
179                                 case aHIDDEN:
180                                         if (server->m.flags & NCP_MOUNT_SYMLINKS) {
181                                                 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
182                                                  && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
183                                                         inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
184                                                         NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
185                                                         break;
186                                                 }
187                                         }
188                                         /* FALLTHROUGH */
189                                 case 0:
190                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
191                                                 inode->i_mode |= S_IRUGO;
192                                         break;
193                                 case aSYSTEM:
194                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
195                                                 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
196                                         break;
197                                 /* case aSYSTEM|aHIDDEN: */
198                                 default:
199                                         /* reserved combination */
200                                         break;
201                         }
202                 }
203 #endif
204         }
205         if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
206 }
207
208 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
209 {
210         NCP_FINFO(inode)->flags = 0;
211         if (!atomic_read(&NCP_FINFO(inode)->opened)) {
212                 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
213                 ncp_update_attrs(inode, nwinfo);
214         }
215
216         ncp_update_dates(inode, &nwinfo->i);
217         ncp_update_dirent(inode, nwinfo);
218 }
219
220 /*
221  * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
222  */
223 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
224 {
225         struct ncp_server *server = NCP_SERVER(inode);
226
227         NCP_FINFO(inode)->flags = 0;
228         
229         ncp_update_attrs(inode, nwinfo);
230
231         DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
232
233         inode->i_nlink = 1;
234         inode->i_uid = server->m.uid;
235         inode->i_gid = server->m.gid;
236
237         ncp_update_dates(inode, &nwinfo->i);
238         ncp_update_inode(inode, nwinfo);
239 }
240
241 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
242 static const struct inode_operations ncp_symlink_inode_operations = {
243         .readlink       = generic_readlink,
244         .follow_link    = page_follow_link_light,
245         .put_link       = page_put_link,
246         .setattr        = ncp_notify_change,
247 };
248 #endif
249
250 /*
251  * Get a new inode.
252  */
253 struct inode * 
254 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
255 {
256         struct inode *inode;
257
258         if (info == NULL) {
259                 printk(KERN_ERR "ncp_iget: info is NULL\n");
260                 return NULL;
261         }
262
263         inode = new_inode(sb);
264         if (inode) {
265                 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
266
267                 inode->i_mapping->backing_dev_info = sb->s_bdi;
268                 inode->i_ino = info->ino;
269                 ncp_set_attr(inode, info);
270                 if (S_ISREG(inode->i_mode)) {
271                         inode->i_op = &ncp_file_inode_operations;
272                         inode->i_fop = &ncp_file_operations;
273                 } else if (S_ISDIR(inode->i_mode)) {
274                         inode->i_op = &ncp_dir_inode_operations;
275                         inode->i_fop = &ncp_dir_operations;
276 #ifdef CONFIG_NCPFS_NFS_NS
277                 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
278                         init_special_inode(inode, inode->i_mode,
279                                 new_decode_dev(info->i.nfs.rdev));
280 #endif
281 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
282                 } else if (S_ISLNK(inode->i_mode)) {
283                         inode->i_op = &ncp_symlink_inode_operations;
284                         inode->i_data.a_ops = &ncp_symlink_aops;
285 #endif
286                 } else {
287                         make_bad_inode(inode);
288                 }
289                 insert_inode_hash(inode);
290         } else
291                 printk(KERN_ERR "ncp_iget: iget failed!\n");
292         return inode;
293 }
294
295 static void
296 ncp_evict_inode(struct inode *inode)
297 {
298         truncate_inode_pages(&inode->i_data, 0);
299         end_writeback(inode);
300
301         if (S_ISDIR(inode->i_mode)) {
302                 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
303         }
304
305         if (ncp_make_closed(inode) != 0) {
306                 /* We can't do anything but complain. */
307                 printk(KERN_ERR "ncp_evict_inode: could not close\n");
308         }
309 }
310
311 static void ncp_stop_tasks(struct ncp_server *server) {
312         struct sock* sk = server->ncp_sock->sk;
313
314         lock_sock(sk);
315         sk->sk_error_report = server->error_report;
316         sk->sk_data_ready   = server->data_ready;
317         sk->sk_write_space  = server->write_space;
318         release_sock(sk);
319         del_timer_sync(&server->timeout_tm);
320         flush_scheduled_work();
321 }
322
323 static int  ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
324 {
325         struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
326         unsigned int tmp;
327
328         if (server->m.uid != 0)
329                 seq_printf(seq, ",uid=%u", server->m.uid);
330         if (server->m.gid != 0)
331                 seq_printf(seq, ",gid=%u", server->m.gid);
332         if (server->m.mounted_uid != 0)
333                 seq_printf(seq, ",owner=%u", server->m.mounted_uid);
334         tmp = server->m.file_mode & S_IALLUGO;
335         if (tmp != NCP_DEFAULT_FILE_MODE)
336                 seq_printf(seq, ",mode=0%o", tmp);
337         tmp = server->m.dir_mode & S_IALLUGO;
338         if (tmp != NCP_DEFAULT_DIR_MODE)
339                 seq_printf(seq, ",dirmode=0%o", tmp);
340         if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
341                 tmp = server->m.time_out * 100 / HZ;
342                 seq_printf(seq, ",timeout=%u", tmp);
343         }
344         if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
345                 seq_printf(seq, ",retry=%u", server->m.retry_count);
346         if (server->m.flags != 0)
347                 seq_printf(seq, ",flags=%lu", server->m.flags);
348         if (server->m.wdog_pid != NULL)
349                 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
350
351         return 0;
352 }
353
354 static const struct ncp_option ncp_opts[] = {
355         { "uid",        OPT_INT,        'u' },
356         { "gid",        OPT_INT,        'g' },
357         { "owner",      OPT_INT,        'o' },
358         { "mode",       OPT_INT,        'm' },
359         { "dirmode",    OPT_INT,        'd' },
360         { "timeout",    OPT_INT,        't' },
361         { "retry",      OPT_INT,        'r' },
362         { "flags",      OPT_INT,        'f' },
363         { "wdogpid",    OPT_INT,        'w' },
364         { "ncpfd",      OPT_INT,        'n' },
365         { "infofd",     OPT_INT,        'i' },  /* v5 */
366         { "version",    OPT_INT,        'v' },
367         { NULL,         0,              0 } };
368
369 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
370         int optval;
371         char *optarg;
372         unsigned long optint;
373         int version = 0;
374         int ret;
375
376         data->flags = 0;
377         data->int_flags = 0;
378         data->mounted_uid = 0;
379         data->wdog_pid = NULL;
380         data->ncp_fd = ~0;
381         data->time_out = NCP_DEFAULT_TIME_OUT;
382         data->retry_count = NCP_DEFAULT_RETRY_COUNT;
383         data->uid = 0;
384         data->gid = 0;
385         data->file_mode = NCP_DEFAULT_FILE_MODE;
386         data->dir_mode = NCP_DEFAULT_DIR_MODE;
387         data->info_fd = -1;
388         data->mounted_vol[0] = 0;
389         
390         while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
391                 ret = optval;
392                 if (ret < 0)
393                         goto err;
394                 switch (optval) {
395                         case 'u':
396                                 data->uid = optint;
397                                 break;
398                         case 'g':
399                                 data->gid = optint;
400                                 break;
401                         case 'o':
402                                 data->mounted_uid = optint;
403                                 break;
404                         case 'm':
405                                 data->file_mode = optint;
406                                 break;
407                         case 'd':
408                                 data->dir_mode = optint;
409                                 break;
410                         case 't':
411                                 data->time_out = optint;
412                                 break;
413                         case 'r':
414                                 data->retry_count = optint;
415                                 break;
416                         case 'f':
417                                 data->flags = optint;
418                                 break;
419                         case 'w':
420                                 data->wdog_pid = find_get_pid(optint);
421                                 break;
422                         case 'n':
423                                 data->ncp_fd = optint;
424                                 break;
425                         case 'i':
426                                 data->info_fd = optint;
427                                 break;
428                         case 'v':
429                                 ret = -ECHRNG;
430                                 if (optint < NCP_MOUNT_VERSION_V4)
431                                         goto err;
432                                 if (optint > NCP_MOUNT_VERSION_V5)
433                                         goto err;
434                                 version = optint;
435                                 break;
436                         
437                 }
438         }
439         return 0;
440 err:
441         put_pid(data->wdog_pid);
442         data->wdog_pid = NULL;
443         return ret;
444 }
445
446 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
447 {
448         struct ncp_mount_data_kernel data;
449         struct ncp_server *server;
450         struct file *ncp_filp;
451         struct inode *root_inode;
452         struct inode *sock_inode;
453         struct socket *sock;
454         int error;
455         int default_bufsize;
456 #ifdef CONFIG_NCPFS_PACKET_SIGNING
457         int options;
458 #endif
459         struct ncp_entry_info finfo;
460
461         data.wdog_pid = NULL;
462         server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
463         if (!server)
464                 return -ENOMEM;
465         sb->s_fs_info = server;
466
467         error = -EFAULT;
468         if (raw_data == NULL)
469                 goto out;
470         switch (*(int*)raw_data) {
471                 case NCP_MOUNT_VERSION:
472                         {
473                                 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
474
475                                 data.flags = md->flags;
476                                 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
477                                 data.mounted_uid = md->mounted_uid;
478                                 data.wdog_pid = find_get_pid(md->wdog_pid);
479                                 data.ncp_fd = md->ncp_fd;
480                                 data.time_out = md->time_out;
481                                 data.retry_count = md->retry_count;
482                                 data.uid = md->uid;
483                                 data.gid = md->gid;
484                                 data.file_mode = md->file_mode;
485                                 data.dir_mode = md->dir_mode;
486                                 data.info_fd = -1;
487                                 memcpy(data.mounted_vol, md->mounted_vol,
488                                         NCP_VOLNAME_LEN+1);
489                         }
490                         break;
491                 case NCP_MOUNT_VERSION_V4:
492                         {
493                                 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
494
495                                 data.flags = md->flags;
496                                 data.int_flags = 0;
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                                 data.mounted_vol[0] = 0;
508                         }
509                         break;
510                 default:
511                         error = -ECHRNG;
512                         if (memcmp(raw_data, "vers", 4) == 0) {
513                                 error = ncp_parse_options(&data, raw_data);
514                         }
515                         if (error)
516                                 goto out;
517                         break;
518         }
519         error = -EBADF;
520         ncp_filp = fget(data.ncp_fd);
521         if (!ncp_filp)
522                 goto out;
523         error = -ENOTSOCK;
524         sock_inode = ncp_filp->f_path.dentry->d_inode;
525         if (!S_ISSOCK(sock_inode->i_mode))
526                 goto out_fput;
527         sock = SOCKET_I(sock_inode);
528         if (!sock)
529                 goto out_fput;
530                 
531         if (sock->type == SOCK_STREAM)
532                 default_bufsize = 0xF000;
533         else
534                 default_bufsize = 1024;
535
536         sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
537         sb->s_maxbytes = 0xFFFFFFFFU;
538         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
539         sb->s_blocksize_bits = 10;
540         sb->s_magic = NCP_SUPER_MAGIC;
541         sb->s_op = &ncp_sops;
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_bdi;
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_fput;
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         /* Althought 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_alloc_root(root_inode);
719         if (!sb->s_root)
720                 goto out_no_root;
721         d_set_d_op(sb->s_root, &ncp_root_dentry_operations);
722         return 0;
723
724 out_no_root:
725         iput(root_inode);
726 out_disconnect:
727         ncp_lock_server(server);
728         ncp_disconnect(server);
729         ncp_unlock_server(server);
730 out_rxbuf:
731         ncp_stop_tasks(server);
732         vfree(server->rxbuf);
733 out_txbuf:
734         vfree(server->txbuf);
735 out_packet:
736         vfree(server->packet);
737 out_nls:
738 #ifdef CONFIG_NCPFS_NLS
739         unload_nls(server->nls_io);
740         unload_nls(server->nls_vol);
741 #endif
742         mutex_destroy(&server->rcv.creq_mutex);
743         mutex_destroy(&server->root_setup_lock);
744         mutex_destroy(&server->mutex);
745 out_fput2:
746         if (server->info_filp)
747                 fput(server->info_filp);
748 out_fput:
749         bdi_destroy(&server->bdi);
750 out_bdi:
751         /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
752          * 
753          * The previously used put_filp(ncp_filp); was bogus, since
754          * it doesn't perform proper unlocking.
755          */
756         fput(ncp_filp);
757 out:
758         put_pid(data.wdog_pid);
759         sb->s_fs_info = NULL;
760         kfree(server);
761         return error;
762 }
763
764 static void ncp_put_super(struct super_block *sb)
765 {
766         struct ncp_server *server = NCP_SBP(sb);
767
768         ncp_lock_server(server);
769         ncp_disconnect(server);
770         ncp_unlock_server(server);
771
772         ncp_stop_tasks(server);
773
774 #ifdef CONFIG_NCPFS_NLS
775         /* unload the NLS charsets */
776         unload_nls(server->nls_vol);
777         unload_nls(server->nls_io);
778 #endif /* CONFIG_NCPFS_NLS */
779         mutex_destroy(&server->rcv.creq_mutex);
780         mutex_destroy(&server->root_setup_lock);
781         mutex_destroy(&server->mutex);
782
783         if (server->info_filp)
784                 fput(server->info_filp);
785         fput(server->ncp_filp);
786         kill_pid(server->m.wdog_pid, SIGTERM, 1);
787         put_pid(server->m.wdog_pid);
788
789         bdi_destroy(&server->bdi);
790         kfree(server->priv.data);
791         kfree(server->auth.object_name);
792         vfree(server->rxbuf);
793         vfree(server->txbuf);
794         vfree(server->packet);
795         sb->s_fs_info = NULL;
796         kfree(server);
797 }
798
799 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
800 {
801         struct dentry* d;
802         struct inode* i;
803         struct ncp_inode_info* ni;
804         struct ncp_server* s;
805         struct ncp_volume_info vi;
806         struct super_block *sb = dentry->d_sb;
807         int err;
808         __u8 dh;
809         
810         d = sb->s_root;
811         if (!d) {
812                 goto dflt;
813         }
814         i = d->d_inode;
815         if (!i) {
816                 goto dflt;
817         }
818         ni = NCP_FINFO(i);
819         if (!ni) {
820                 goto dflt;
821         }
822         s = NCP_SBP(sb);
823         if (!s) {
824                 goto dflt;
825         }
826         if (!s->m.mounted_vol[0]) {
827                 goto dflt;
828         }
829
830         err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
831         if (err) {
832                 goto dflt;
833         }
834         err = ncp_get_directory_info(s, dh, &vi);
835         ncp_dirhandle_free(s, dh);
836         if (err) {
837                 goto dflt;
838         }
839         buf->f_type = NCP_SUPER_MAGIC;
840         buf->f_bsize = vi.sectors_per_block * 512;
841         buf->f_blocks = vi.total_blocks;
842         buf->f_bfree = vi.free_blocks;
843         buf->f_bavail = vi.free_blocks;
844         buf->f_files = vi.total_dir_entries;
845         buf->f_ffree = vi.available_dir_entries;
846         buf->f_namelen = 12;
847         return 0;
848
849         /* We cannot say how much disk space is left on a mounted
850            NetWare Server, because free space is distributed over
851            volumes, and the current user might have disk quotas. So
852            free space is not that simple to determine. Our decision
853            here is to err conservatively. */
854
855 dflt:;
856         buf->f_type = NCP_SUPER_MAGIC;
857         buf->f_bsize = NCP_BLOCK_SIZE;
858         buf->f_blocks = 0;
859         buf->f_bfree = 0;
860         buf->f_bavail = 0;
861         buf->f_namelen = 12;
862         return 0;
863 }
864
865 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
866 {
867         struct inode *inode = dentry->d_inode;
868         int result = 0;
869         __le32 info_mask;
870         struct nw_modify_dos_info info;
871         struct ncp_server *server;
872
873         result = -EIO;
874
875         server = NCP_SERVER(inode);
876         if (!server)    /* How this could happen? */
877                 goto out;
878
879         /* ageing the dentry to force validation */
880         ncp_age_dentry(server, dentry);
881
882         result = inode_change_ok(inode, attr);
883         if (result < 0)
884                 goto out;
885
886         result = -EPERM;
887         if (((attr->ia_valid & ATTR_UID) &&
888              (attr->ia_uid != server->m.uid)))
889                 goto out;
890
891         if (((attr->ia_valid & ATTR_GID) &&
892              (attr->ia_gid != server->m.gid)))
893                 goto out;
894
895         if (((attr->ia_valid & ATTR_MODE) &&
896              (attr->ia_mode &
897               ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
898                 goto out;
899
900         info_mask = 0;
901         memset(&info, 0, sizeof(info));
902
903 #if 1 
904         if ((attr->ia_valid & ATTR_MODE) != 0)
905         {
906                 umode_t newmode = attr->ia_mode;
907
908                 info_mask |= DM_ATTRIBUTES;
909
910                 if (S_ISDIR(inode->i_mode)) {
911                         newmode &= server->m.dir_mode;
912                 } else {
913 #ifdef CONFIG_NCPFS_EXTRAS                      
914                         if (server->m.flags & NCP_MOUNT_EXTRAS) {
915                                 /* any non-default execute bit set */
916                                 if (newmode & ~server->m.file_mode & S_IXUGO)
917                                         info.attributes |= aSHARED | aSYSTEM;
918                                 /* read for group/world and not in default file_mode */
919                                 else if (newmode & ~server->m.file_mode & S_IRUGO)
920                                         info.attributes |= aSHARED;
921                         } else
922 #endif
923                                 newmode &= server->m.file_mode;                 
924                 }
925                 if (newmode & S_IWUGO)
926                         info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
927                 else
928                         info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
929
930 #ifdef CONFIG_NCPFS_NFS_NS
931                 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
932                         result = ncp_modify_nfs_info(server,
933                                                      NCP_FINFO(inode)->volNumber,
934                                                      NCP_FINFO(inode)->dirEntNum,
935                                                      attr->ia_mode, 0);
936                         if (result != 0)
937                                 goto out;
938                         info.attributes &= ~(aSHARED | aSYSTEM);
939                         {
940                                 /* mark partial success */
941                                 struct iattr tmpattr;
942                                 
943                                 tmpattr.ia_valid = ATTR_MODE;
944                                 tmpattr.ia_mode = attr->ia_mode;
945
946                                 setattr_copy(inode, &tmpattr);
947                                 mark_inode_dirty(inode);
948                         }
949                 }
950 #endif
951         }
952 #endif
953
954         /* Do SIZE before attributes, otherwise mtime together with size does not work...
955          */
956         if ((attr->ia_valid & ATTR_SIZE) != 0) {
957                 int written;
958
959                 DPRINTK("ncpfs: trying to change size to %ld\n",
960                         attr->ia_size);
961
962                 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
963                         result = -EACCES;
964                         goto out;
965                 }
966                 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
967                           attr->ia_size, 0, "", &written);
968
969                 /* According to ndir, the changes only take effect after
970                    closing the file */
971                 ncp_inode_close(inode);
972                 result = ncp_make_closed(inode);
973                 if (result)
974                         goto out;
975
976                 if (attr->ia_size != i_size_read(inode)) {
977                         result = vmtruncate(inode, attr->ia_size);
978                         if (result)
979                                 goto out;
980                         mark_inode_dirty(inode);
981                 }
982         }
983         if ((attr->ia_valid & ATTR_CTIME) != 0) {
984                 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
985                 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
986                              &info.creationTime, &info.creationDate);
987         }
988         if ((attr->ia_valid & ATTR_MTIME) != 0) {
989                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
990                 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
991                                   &info.modifyTime, &info.modifyDate);
992         }
993         if ((attr->ia_valid & ATTR_ATIME) != 0) {
994                 __le16 dummy;
995                 info_mask |= (DM_LAST_ACCESS_DATE);
996                 ncp_date_unix2dos(attr->ia_atime.tv_sec,
997                                   &dummy, &info.lastAccessDate);
998         }
999         if (info_mask != 0) {
1000                 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1001                                       inode, info_mask, &info);
1002                 if (result != 0) {
1003                         if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1004                                 /* NetWare seems not to allow this. I
1005                                    do not know why. So, just tell the
1006                                    user everything went fine. This is
1007                                    a terrible hack, but I do not know
1008                                    how to do this correctly. */
1009                                 result = 0;
1010                         } else
1011                                 goto out;
1012                 }
1013 #ifdef CONFIG_NCPFS_STRONG              
1014                 if ((!result) && (info_mask & DM_ATTRIBUTES))
1015                         NCP_FINFO(inode)->nwattr = info.attributes;
1016 #endif
1017         }
1018         if (result)
1019                 goto out;
1020
1021         setattr_copy(inode, attr);
1022         mark_inode_dirty(inode);
1023
1024 out:
1025         if (result > 0)
1026                 result = -EACCES;
1027         return result;
1028 }
1029
1030 static struct dentry *ncp_mount(struct file_system_type *fs_type,
1031         int flags, const char *dev_name, void *data)
1032 {
1033         return mount_nodev(fs_type, flags, data, ncp_fill_super);
1034 }
1035
1036 static struct file_system_type ncp_fs_type = {
1037         .owner          = THIS_MODULE,
1038         .name           = "ncpfs",
1039         .mount          = ncp_mount,
1040         .kill_sb        = kill_anon_super,
1041         .fs_flags       = FS_BINARY_MOUNTDATA,
1042 };
1043
1044 static int __init init_ncp_fs(void)
1045 {
1046         int err;
1047         DPRINTK("ncpfs: init_ncp_fs called\n");
1048
1049         err = init_inodecache();
1050         if (err)
1051                 goto out1;
1052         err = register_filesystem(&ncp_fs_type);
1053         if (err)
1054                 goto out;
1055         return 0;
1056 out:
1057         destroy_inodecache();
1058 out1:
1059         return err;
1060 }
1061
1062 static void __exit exit_ncp_fs(void)
1063 {
1064         DPRINTK("ncpfs: exit_ncp_fs called\n");
1065         unregister_filesystem(&ncp_fs_type);
1066         destroy_inodecache();
1067 }
1068
1069 module_init(init_ncp_fs)
1070 module_exit(exit_ncp_fs)
1071 MODULE_LICENSE("GPL");