~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/ncpfs/inode.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp