Import 2.1.89
[davej-history.git] / fs / ncpfs / inode.c
blobf11f4640c4d4f8b250162d2648354e942732b6e9
1 /*
2 * inode.c
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
8 */
10 #include <linux/config.h>
11 #include <linux/module.h>
13 #include <asm/system.h>
14 #include <asm/uaccess.h>
15 #include <asm/byteorder.h>
17 #include <linux/sched.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/locks.h>
24 #include <linux/file.h>
25 #include <linux/fcntl.h>
26 #include <linux/malloc.h>
27 #include <linux/init.h>
28 #ifdef CONFIG_KERNELD
29 #include <linux/kerneld.h>
30 #endif
32 #include <linux/ncp_fs.h>
33 #include"ncplib_kernel.h"
35 static voidncp_read_inode(struct inode *);
36 static voidncp_put_inode(struct inode *);
37 static voidncp_delete_inode(struct inode *);
38 static voidncp_put_super(struct super_block *);
39 static intncp_statfs(struct super_block *,struct statfs *,int);
41 static struct super_operations ncp_sops =
43 ncp_read_inode,/* read inode */
44 NULL,/* write inode */
45 ncp_put_inode,/* put inode */
46 ncp_delete_inode,/* delete inode */
47 ncp_notify_change,/* notify change */
48 ncp_put_super,/* put superblock */
49 NULL,/* write superblock */
50 ncp_statfs,/* stat filesystem */
51 NULL /* remount */
54 externstruct dentry_operations ncp_dentry_operations;
56 static struct nw_file_info *read_nwinfo = NULL;
57 static struct semaphore read_sem = MUTEX;
60 * Fill in the ncpfs-specific information in the inode.
62 voidncp_update_inode(struct inode *inode,struct nw_file_info *nwinfo)
64 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
65 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
66 NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
68 NCP_FINFO(inode)->opened = nwinfo->opened;
69 NCP_FINFO(inode)->access = nwinfo->access;
70 NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
71 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
72 sizeof(nwinfo->file_handle));
73 #ifdef NCPFS_DEBUG_VERBOSE
74 printk(KERN_DEBUG "ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
75 nwinfo->i.entryName,NCP_FINFO(inode)->volNumber,NCP_FINFO(inode)->dirEntNum);
76 #endif
79 voidncp_update_inode2(struct inode* inode,struct nw_file_info *nwinfo)
81 struct nw_info_struct *nwi = &nwinfo->i;
82 struct ncp_server *server =NCP_SERVER(inode);
84 if(!NCP_FINFO(inode)->opened) {
85 if(nwi->attributes & aDIR) {
86 inode->i_mode = server->m.dir_mode;
87 inode->i_size =512;
88 }else{
89 inode->i_mode = server->m.file_mode;
90 inode->i_size =le32_to_cpu(nwi->dataStreamSize);
92 if(nwi->attributes & aRONLY) inode->i_mode &= ~0222;
94 inode->i_blocks =0;
95 if((inode->i_size)&&(inode->i_blksize)) {
96 inode->i_blocks = (inode->i_size-1)/(inode->i_blksize)+1;
98 /* TODO: times? I'm not sure... */
99 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
100 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
101 NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
105 * Fill in the inode based on the nw_file_info structure.
107 static voidncp_set_attr(struct inode *inode,struct nw_file_info *nwinfo)
109 struct nw_info_struct *nwi = &nwinfo->i;
110 struct ncp_server *server =NCP_SERVER(inode);
112 if(nwi->attributes & aDIR) {
113 inode->i_mode = server->m.dir_mode;
114 /* for directories dataStreamSize seems to be some
115 Object ID ??? */
116 inode->i_size =512;
117 }else{
118 inode->i_mode = server->m.file_mode;
119 inode->i_size =le32_to_cpu(nwi->dataStreamSize);
121 if(nwi->attributes & aRONLY) inode->i_mode &= ~0222;
123 DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
125 inode->i_nlink =1;
126 inode->i_uid = server->m.uid;
127 inode->i_gid = server->m.gid;
128 inode->i_blksize =512;
129 inode->i_rdev =0;
131 inode->i_blocks =0;
132 if((inode->i_blksize !=0) && (inode->i_size !=0)) {
133 inode->i_blocks =
134 (inode->i_size -1) / inode->i_blksize +1;
137 inode->i_mtime =ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
138 le16_to_cpu(nwi->modifyDate));
139 inode->i_ctime =ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
140 le16_to_cpu(nwi->creationDate));
141 inode->i_atime =ncp_date_dos2unix(0,
142 le16_to_cpu(nwi->lastAccessDate));
143 ncp_update_inode(inode, nwinfo);
147 * This is called from iget() with the read semaphore held.
148 * The global ncpfs_file_info structure has been set up by ncp_iget.
150 static voidncp_read_inode(struct inode *inode)
152 if(read_nwinfo == NULL) {
153 printk(KERN_ERR "ncp_read_inode: invalid call\n");
154 return;
157 ncp_set_attr(inode, read_nwinfo);
159 if(S_ISREG(inode->i_mode)) {
160 inode->i_op = &ncp_file_inode_operations;
161 }else if(S_ISDIR(inode->i_mode)) {
162 inode->i_op = &ncp_dir_inode_operations;
163 }else{
164 inode->i_op = NULL;
169 * Set up the ncpfs_inode_info pointer and get a new inode.
171 struct inode *
172 ncp_iget(struct super_block *sb,struct ncpfs_inode_info *info)
174 struct inode *inode;
176 if(info == NULL) {
177 printk(KERN_ERR "ncp_iget: info is NULL\n");
178 return NULL;
181 down(&read_sem);
182 read_nwinfo = &info->nw_info;
183 inode =iget(sb, info->ino);
184 read_nwinfo = NULL;
185 up(&read_sem);
186 if(!inode)
187 printk(KERN_ERR "ncp_iget: iget failed!\n");
188 return inode;
191 static voidncp_put_inode(struct inode *inode)
193 if(inode->i_count ==1)
194 inode->i_nlink =0;
197 static void
198 ncp_delete_inode(struct inode *inode)
200 if(S_ISDIR(inode->i_mode)) {
201 DDPRINTK(KERN_DEBUG "ncp_delete_inode: put directory %ld\n", inode->i_ino);
202 ncp_invalid_dir_cache(inode);
205 if(NCP_FINFO(inode)->opened &&ncp_make_closed(inode) !=0) {
206 /* We can't do anything but complain. */
207 printk(KERN_ERR "ncp_delete_inode: could not close\n");
209 clear_inode(inode);
212 static voidncp_init_root(struct ncp_server *server,
213 struct ncpfs_inode_info *info)
215 struct ncp_inode_info *root = &(server->root);
216 struct nw_info_struct *i = &(root->finfo.i);
217 unsigned short dummy;
219 DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
221 i->attributes = aDIR;
222 i->dataStreamSize=1024;
223 i->dirEntNum =0;
224 i->DosDirNum =0;
225 i->volNumber = NCP_NUMBER_OF_VOLUMES +1;/* illegal volnum */
226 ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
227 ncp_date_unix2dos(0, &(i->modifyTime ), &(i->modifyDate));
228 ncp_date_unix2dos(0, &(dummy ), &(i->lastAccessDate));
229 i->creationTime =le16_to_cpu(i->creationTime);
230 i->creationDate =le16_to_cpu(i->creationDate);
231 i->modifyTime =le16_to_cpu(i->modifyTime);
232 i->modifyDate =le16_to_cpu(i->modifyDate);
233 i->lastAccessDate=le16_to_cpu(i->lastAccessDate);
234 i->nameLen =0;
235 i->entryName[0] ='\0';
237 root->finfo.opened=0;
238 info->ino =2;/* tradition */
239 info->nw_info = root->finfo;
240 return;
243 struct super_block *
244 ncp_read_super(struct super_block *sb,void*raw_data,int silent)
246 struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
247 struct ncp_server *server;
248 struct file *ncp_filp;
249 struct inode *root_inode;
250 kdev_t dev = sb->s_dev;
251 int error;
252 #ifdef CONFIG_NCPFS_PACKET_SIGNING
253 int options;
254 #endif
255 struct ncpfs_inode_info finfo;
257 MOD_INC_USE_COUNT;
258 if(data == NULL)
259 goto out_no_data;
260 if(data->version != NCP_MOUNT_VERSION)
261 goto out_bad_mount;
262 ncp_filp =fget(data->ncp_fd);
263 if(!ncp_filp)
264 goto out_bad_file;
265 if(!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
266 goto out_bad_file2;
268 lock_super(sb);
270 sb->s_blocksize =1024;/* Eh... Is this correct? */
271 sb->s_blocksize_bits =10;
272 sb->s_magic = NCP_SUPER_MAGIC;
273 sb->s_dev = dev;
274 sb->s_op = &ncp_sops;
276 /* We must malloc our own super-block info */
277 server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
278 GFP_KERNEL);
279 if(server == NULL)
280 goto out_no_server;
281 NCP_SBP(sb) = server;
283 server->ncp_filp = ncp_filp;
284 server->lock =0;
285 server->wait = NULL;
286 server->packet = NULL;
287 server->buffer_size =0;
288 server->conn_status =0;
289 server->root_dentry = NULL;
290 #ifdef CONFIG_NCPFS_PACKET_SIGNING
291 server->sign_wanted =0;
292 server->sign_active =0;
293 #endif
294 server->auth.auth_type = NCP_AUTH_NONE;
295 server->auth.object_name_len =0;
296 server->auth.object_name = NULL;
297 server->auth.object_type =0;
298 server->priv.len =0;
299 server->priv.data = NULL;
301 server->m = *data;
302 /* Althought anything producing this is buggy, it happens
303 now because of PATH_MAX changes.. */
304 if(server->m.time_out <10) {
305 server->m.time_out =10;
306 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
308 server->m.file_mode = (server->m.file_mode &
309 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
310 server->m.dir_mode = (server->m.dir_mode &
311 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
313 server->packet_size = NCP_PACKET_SIZE;
314 server->packet =ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
315 if(server->packet == NULL)
316 goto out_no_packet;
318 ncp_lock_server(server);
319 error =ncp_connect(server);
320 ncp_unlock_server(server);
321 if(error <0)
322 goto out_no_connect;
323 DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
325 #ifdef CONFIG_NCPFS_PACKET_SIGNING
326 if(ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
327 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) ==0)
329 if(options != NCP_DEFAULT_OPTIONS)
331 if(ncp_negotiate_size_and_options(server,
332 NCP_DEFAULT_BUFSIZE,
333 options &2,
334 &(server->buffer_size), &options) !=0)
337 goto out_no_bufsize;
340 if(options &2)
341 server->sign_wanted =1;
343 else
344 #endif/* CONFIG_NCPFS_PACKET_SIGNING */
345 if(ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
346 &(server->buffer_size)) !=0)
347 goto out_no_bufsize;
348 DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);
350 ncp_init_root(server, &finfo);
351 server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS;
352 root_inode =ncp_iget(sb, &finfo);
353 if(!root_inode)
354 goto out_no_root;
355 DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n",NCP_FINFO(root_inode)->volNumber);
356 server->root_dentry = sb->s_root =d_alloc_root(root_inode, NULL);
357 if(!sb->s_root)
358 goto out_no_root;
359 server->root_dentry->d_op = &ncp_dentry_operations;
360 unlock_super(sb);
361 return sb;
363 out_no_root:
364 printk(KERN_ERR "ncp_read_super: get root inode failed\n");
365 iput(root_inode);
366 goto out_disconnect;
367 out_no_bufsize:
368 printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
369 out_disconnect:
370 ncp_lock_server(server);
371 ncp_disconnect(server);
372 ncp_unlock_server(server);
373 goto out_free_packet;
374 out_no_connect:
375 printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
376 out_free_packet:
377 ncp_kfree_s(server->packet, server->packet_size);
378 goto out_free_server;
379 out_no_packet:
380 printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
381 out_free_server:
382 ncp_kfree_s(NCP_SBP(sb),sizeof(struct ncp_server));
383 goto out_unlock;
384 out_no_server:
385 printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
386 out_unlock:
387 put_filp(ncp_filp);
388 unlock_super(sb);
389 goto out;
391 out_bad_file2:
392 fput(ncp_filp);
393 out_bad_file:
394 printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
395 goto out;
396 out_bad_mount:
397 printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
398 NCP_MOUNT_VERSION);
399 goto out;
400 out_no_data:
401 printk(KERN_ERR "ncp_read_super: missing data argument\n");
402 out:
403 sb->s_dev =0;
404 MOD_DEC_USE_COUNT;
405 return NULL;
408 static voidncp_put_super(struct super_block *sb)
410 struct ncp_server *server =NCP_SBP(sb);
412 lock_super(sb);
414 ncp_lock_server(server);
415 ncp_disconnect(server);
416 ncp_unlock_server(server);
418 fput(server->ncp_filp);
419 kill_proc(server->m.wdog_pid, SIGTERM,1);
421 if(server->priv.data)
422 ncp_kfree_s(server->priv.data, server->priv.len);
423 if(server->auth.object_name)
424 ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
425 ncp_kfree_s(server->packet, server->packet_size);
427 ncp_kfree_s(NCP_SBP(sb),sizeof(struct ncp_server));
429 sb->s_dev =0;
430 unlock_super(sb);
432 MOD_DEC_USE_COUNT;
435 static intncp_statfs(struct super_block *sb,struct statfs *buf,int bufsiz)
437 struct statfs tmp;
439 /* We cannot say how much disk space is left on a mounted
440 NetWare Server, because free space is distributed over
441 volumes, and the current user might have disk quotas. So
442 free space is not that simple to determine. Our decision
443 here is to err conservatively. */
445 tmp.f_type = NCP_SUPER_MAGIC;
446 tmp.f_bsize =512;
447 tmp.f_blocks =0;
448 tmp.f_bfree =0;
449 tmp.f_bavail =0;
450 tmp.f_files = -1;
451 tmp.f_ffree = -1;
452 tmp.f_namelen =12;
453 returncopy_to_user(buf, &tmp, bufsiz) ? -EFAULT :0;
456 intncp_notify_change(struct dentry *dentry,struct iattr *attr)
458 struct inode *inode = dentry->d_inode;
459 int result =0;
460 int info_mask;
461 struct nw_modify_dos_info info;
463 result = -EIO;
464 if(!ncp_conn_valid(NCP_SERVER(inode)))
465 goto out;
467 result =inode_change_ok(inode, attr);
468 if(result <0)
469 goto out;
471 result = -EPERM;
472 if(((attr->ia_valid & ATTR_UID) &&
473 (attr->ia_uid !=NCP_SERVER(inode)->m.uid)))
474 goto out;
476 if(((attr->ia_valid & ATTR_GID) &&
477 (attr->ia_uid !=NCP_SERVER(inode)->m.gid)))
478 goto out;
480 if(((attr->ia_valid & ATTR_MODE) &&
481 (attr->ia_mode &
482 ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
483 goto out;
485 info_mask =0;
486 memset(&info,0,sizeof(info));
488 #if 1
489 if((attr->ia_valid & ATTR_MODE) !=0)
491 if(!S_ISREG(inode->i_mode))
493 return-EPERM;
495 else
497 umode_t newmode;
499 info_mask |= DM_ATTRIBUTES;
500 newmode=attr->ia_mode;
501 newmode &=NCP_SERVER(inode)->m.file_mode;
503 if(newmode &0222)/* any write bit set */
505 info.attributes &= ~0x60001;
507 else
509 info.attributes |=0x60001;
513 #endif
515 if((attr->ia_valid & ATTR_CTIME) !=0) {
516 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
517 ncp_date_unix2dos(attr->ia_ctime,
518 &(info.creationTime), &(info.creationDate));
519 info.creationTime =le16_to_cpu(info.creationTime);
520 info.creationDate =le16_to_cpu(info.creationDate);
522 if((attr->ia_valid & ATTR_MTIME) !=0) {
523 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
524 ncp_date_unix2dos(attr->ia_mtime,
525 &(info.modifyTime), &(info.modifyDate));
526 info.modifyTime =le16_to_cpu(info.modifyTime);
527 info.modifyDate =le16_to_cpu(info.modifyDate);
529 if((attr->ia_valid & ATTR_ATIME) !=0) {
530 __u16 dummy;
531 info_mask |= (DM_LAST_ACCESS_DATE);
532 ncp_date_unix2dos(attr->ia_ctime,
533 &(dummy), &(info.lastAccessDate));
534 info.lastAccessDate =le16_to_cpu(info.lastAccessDate);
536 if(info_mask !=0) {
537 result =ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
538 inode, info_mask, &info);
539 if(result !=0) {
540 result = -EACCES;
542 if(info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
543 /* NetWare seems not to allow this. I
544 do not know why. So, just tell the
545 user everything went fine. This is
546 a terrible hack, but I do not know
547 how to do this correctly. */
548 result =0;
552 if((attr->ia_valid & ATTR_SIZE) !=0) {
553 int written;
555 DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
556 attr->ia_size);
558 if((result =ncp_make_open(inode, O_RDWR)) <0) {
559 return-EACCES;
561 ncp_write(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
562 attr->ia_size,0,"", &written);
564 /* According to ndir, the changes only take effect after
565 closing the file */
566 result =ncp_make_closed(inode);
568 ncp_invalid_dir_cache(dentry->d_parent->d_inode);
569 out:
570 return result;
573 #ifdef DEBUG_NCP_MALLOC
574 int ncp_malloced;
575 int ncp_current_malloced;
576 #endif
578 static struct file_system_type ncp_fs_type = {
579 "ncpfs",
580 0/* FS_NO_DCACHE doesn't work correctly */,
581 ncp_read_super,
582 NULL
585 __initfunc(intinit_ncp_fs(void))
587 returnregister_filesystem(&ncp_fs_type);
590 #ifdef MODULE
591 EXPORT_NO_SYMBOLS;
593 intinit_module(void)
595 DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
597 read_sem = MUTEX;
598 read_nwinfo = NULL;
600 #ifdef DEBUG_NCP_MALLOC
601 ncp_malloced =0;
602 ncp_current_malloced =0;
603 #endif
604 ncp_init_dir_cache();
606 returninit_ncp_fs();
609 voidcleanup_module(void)
611 DPRINTK(KERN_DEBUG "ncpfs: cleanup_module called\n");
612 ncp_free_dir_cache();
613 unregister_filesystem(&ncp_fs_type);
614 #ifdef DEBUG_NCP_MALLOC
615 printk(KERN_DEBUG "ncp_malloced: %d\n", ncp_malloced);
616 printk(KERN_DEBUG "ncp_current_malloced: %d\n", ncp_current_malloced);
617 #endif
620 #endif
close