Linux 2.3.1pre3
[davej-history.git] / fs / ncpfs / inode.c
blobf7d4765c9e0aea227d82d93389afe019f1fe48ed
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
7 * Modified 1998 Wolfram Pienkoss for NLS
9 */
11 #include <linux/config.h>
12 #include <linux/module.h>
14 #include <asm/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
18 #include <linux/sched.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/locks.h>
25 #include <linux/file.h>
26 #include <linux/fcntl.h>
27 #include <linux/malloc.h>
28 #include <linux/init.h>
30 #include <linux/ncp_fs.h>
32 #include "ncplib_kernel.h"
34 static void ncp_read_inode(struct inode *);
35 static void ncp_put_inode(struct inode *);
36 static void ncp_delete_inode(struct inode *);
37 static void ncp_put_super(struct super_block *);
38 static int ncp_statfs(struct super_block *, struct statfs *, int);
40 static struct super_operations ncp_sops =
42 ncp_read_inode, /* read inode */
43 NULL, /* write inode */
44 ncp_put_inode, /* put inode */
45 ncp_delete_inode, /* delete inode */
46 ncp_notify_change, /* notify change */
47 ncp_put_super, /* put superblock */
48 NULL, /* write superblock */
49 ncp_statfs, /* stat filesystem */
50 NULL /* remount */
53 extern struct dentry_operations ncp_dentry_operations;
54 #ifdef CONFIG_NCPFS_EXTRAS
55 extern struct inode_operations ncp_symlink_inode_operations;
56 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
57 #endif
59 static struct nw_file_info *read_nwinfo = NULL;
60 static DECLARE_MUTEX(read_sem);
63 * Fill in the ncpfs-specific information in the inode.
65 void ncp_update_inode(struct inode *inode, struct nw_file_info *nwinfo)
67 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
68 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
69 NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
71 #ifdef CONFIG_NCPFS_SMALLDOS
72 NCP_FINFO(inode)->origNS = nwinfo->i.NSCreator;
73 #endif
74 #ifdef CONFIG_NCPFS_STRONG
75 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
76 #endif
77 NCP_FINFO(inode)->opened = nwinfo->opened;
78 NCP_FINFO(inode)->access = nwinfo->access;
79 NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
80 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
81 sizeof(nwinfo->file_handle));
82 #ifdef NCPFS_DEBUG_VERBOSE
83 printk(KERN_DEBUG "ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
84 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum);
85 #endif
88 void ncp_update_inode2(struct inode* inode, struct nw_file_info *nwinfo)
90 struct nw_info_struct *nwi = &nwinfo->i;
91 struct ncp_server *server = NCP_SERVER(inode);
93 if (!NCP_FINFO(inode)->opened) {
94 #ifdef CONFIG_NCPFS_STRONG
95 NCP_FINFO(inode)->nwattr = nwi->attributes;
96 #endif
97 if (nwi->attributes & aDIR) {
98 inode->i_mode = server->m.dir_mode;
99 inode->i_size = 512;
100 } else {
101 inode->i_mode = server->m.file_mode;
102 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
103 #ifdef CONFIG_NCPFS_EXTRAS
104 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
105 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
106 case aHIDDEN:
107 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
108 if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
109 && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
110 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
111 break;
114 /* FALLTHROUGH */
115 case 0:
116 if (server->m.flags & NCP_MOUNT_EXTRAS)
117 inode->i_mode |= 0444;
118 break;
119 case aSYSTEM:
120 if (server->m.flags & NCP_MOUNT_EXTRAS)
121 inode->i_mode |= (inode->i_mode >> 2) & 0111;
122 break;
123 /* case aSYSTEM|aHIDDEN: */
124 default:
125 /* reserved combination */
126 break;
129 #endif
131 if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
133 inode->i_blocks = 0;
134 if ((inode->i_size)&&(inode->i_blksize)) {
135 inode->i_blocks = (inode->i_size-1)/(inode->i_blksize)+1;
137 /* TODO: times? I'm not sure... */
138 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
139 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
140 NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
144 * Fill in the inode based on the nw_file_info structure.
146 static void ncp_set_attr(struct inode *inode, struct nw_file_info *nwinfo)
148 struct nw_info_struct *nwi = &nwinfo->i;
149 struct ncp_server *server = NCP_SERVER(inode);
151 if (nwi->attributes & aDIR) {
152 inode->i_mode = server->m.dir_mode;
153 /* for directories dataStreamSize seems to be some
154 Object ID ??? */
155 inode->i_size = 512;
156 } else {
157 inode->i_mode = server->m.file_mode;
158 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
159 #ifdef CONFIG_NCPFS_EXTRAS
160 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
161 && (nwi->attributes & aSHARED)) {
162 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
163 case aHIDDEN:
164 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
165 if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
166 && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
167 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
168 break;
171 /* FALLTHROUGH */
172 case 0:
173 if (server->m.flags & NCP_MOUNT_EXTRAS)
174 inode->i_mode |= 0444;
175 break;
176 case aSYSTEM:
177 if (server->m.flags & NCP_MOUNT_EXTRAS)
178 inode->i_mode |= (inode->i_mode >> 2) & 0111;
179 break;
180 /* case aSYSTEM|aHIDDEN: */
181 default:
182 /* reserved combination */
183 break;
186 #endif
188 if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
190 DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
192 inode->i_nlink = 1;
193 inode->i_uid = server->m.uid;
194 inode->i_gid = server->m.gid;
195 inode->i_blksize = 512;
196 inode->i_rdev = 0;
198 inode->i_blocks = 0;
199 if ((inode->i_blksize != 0) && (inode->i_size != 0)) {
200 inode->i_blocks =
201 (inode->i_size - 1) / inode->i_blksize + 1;
204 inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
205 le16_to_cpu(nwi->modifyDate));
206 inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
207 le16_to_cpu(nwi->creationDate));
208 inode->i_atime = ncp_date_dos2unix(0,
209 le16_to_cpu(nwi->lastAccessDate));
210 ncp_update_inode(inode, nwinfo);
214 * This is called from iget() with the read semaphore held.
215 * The global ncpfs_file_info structure has been set up by ncp_iget.
217 static void ncp_read_inode(struct inode *inode)
219 if (read_nwinfo == NULL) {
220 printk(KERN_ERR "ncp_read_inode: invalid call\n");
221 return;
224 ncp_set_attr(inode, read_nwinfo);
226 if (S_ISREG(inode->i_mode)) {
227 inode->i_op = &ncp_file_inode_operations;
228 } else if (S_ISDIR(inode->i_mode)) {
229 inode->i_op = &ncp_dir_inode_operations;
230 #ifdef CONFIG_NCPFS_EXTRAS
231 } else if (S_ISLNK(inode->i_mode)) {
232 inode->i_op = &ncp_symlink_inode_operations;
233 #endif
234 } else {
235 inode->i_op = NULL;
240 * Set up the ncpfs_inode_info pointer and get a new inode.
242 struct inode *
243 ncp_iget(struct super_block *sb, struct ncpfs_inode_info *info)
245 struct inode *inode;
247 if (info == NULL) {
248 printk(KERN_ERR "ncp_iget: info is NULL\n");
249 return NULL;
252 down(&read_sem);
253 read_nwinfo = &info->nw_info;
254 inode = iget(sb, info->ino);
255 read_nwinfo = NULL;
256 up(&read_sem);
257 if (!inode)
258 printk(KERN_ERR "ncp_iget: iget failed!\n");
259 return inode;
262 static void ncp_put_inode(struct inode *inode)
264 if (inode->i_count == 1)
265 inode->i_nlink = 0;
268 static void
269 ncp_delete_inode(struct inode *inode)
271 if (S_ISDIR(inode->i_mode)) {
272 DDPRINTK(KERN_DEBUG "ncp_delete_inode: put directory %ld\n", inode->i_ino);
273 ncp_invalid_dir_cache(inode);
276 if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
277 /* We can't do anything but complain. */
278 printk(KERN_ERR "ncp_delete_inode: could not close\n");
280 clear_inode(inode);
283 static void ncp_init_root(struct ncp_server *server,
284 struct ncpfs_inode_info *info)
286 struct ncp_inode_info *root = &(server->root);
287 struct nw_info_struct *i = &(root->finfo.i);
289 DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
291 i->attributes = aDIR;
292 i->dataStreamSize= 1024;
293 i->dirEntNum = 0;
294 i->DosDirNum = 0;
295 #ifdef CONFIG_NCPFS_SMALLDOS
296 i->NSCreator = NW_NS_DOS;
297 #endif
298 i->volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */
299 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
300 i->creationTime = i->modifyTime = cpu_to_le16(0x0000);
301 i->creationDate = i->modifyDate = i->lastAccessDate = cpu_to_le16(0x0C21);
302 i->nameLen = 0;
303 i->entryName[0] = '\0';
305 root->finfo.opened= 0;
306 info->ino = 2; /* tradition */
307 info->nw_info = root->finfo;
308 return;
311 struct super_block *
312 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
314 struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
315 struct ncp_server *server;
316 struct file *ncp_filp;
317 struct inode *root_inode;
318 kdev_t dev = sb->s_dev;
319 int error;
320 #ifdef CONFIG_NCPFS_PACKET_SIGNING
321 int options;
322 #endif
323 struct ncpfs_inode_info finfo;
325 MOD_INC_USE_COUNT;
326 if (data == NULL)
327 goto out_no_data;
328 if (data->version != NCP_MOUNT_VERSION)
329 goto out_bad_mount;
330 ncp_filp = fget(data->ncp_fd);
331 if (!ncp_filp)
332 goto out_bad_file;
333 if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
334 goto out_bad_file2;
336 lock_super(sb);
338 sb->s_blocksize = 1024; /* Eh... Is this correct? */
339 sb->s_blocksize_bits = 10;
340 sb->s_magic = NCP_SUPER_MAGIC;
341 sb->s_dev = dev;
342 sb->s_op = &ncp_sops;
344 /* We must malloc our own super-block info */
345 server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
346 GFP_KERNEL);
347 if (server == NULL)
348 goto out_no_server;
349 NCP_SBP(sb) = server;
351 server->ncp_filp = ncp_filp;
352 server->lock = 0;
353 init_waitqueue_head(&server->wait);
354 server->packet = NULL;
355 server->buffer_size = 0;
356 server->conn_status = 0;
357 server->root_dentry = NULL;
358 server->root_setuped = 0;
359 #ifdef CONFIG_NCPFS_PACKET_SIGNING
360 server->sign_wanted = 0;
361 server->sign_active = 0;
362 #endif
363 server->auth.auth_type = NCP_AUTH_NONE;
364 server->auth.object_name_len = 0;
365 server->auth.object_name = NULL;
366 server->auth.object_type = 0;
367 server->priv.len = 0;
368 server->priv.data = NULL;
370 server->m = *data;
371 /* Althought anything producing this is buggy, it happens
372 now because of PATH_MAX changes.. */
373 if (server->m.time_out < 10) {
374 server->m.time_out = 10;
375 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
377 server->m.file_mode = (server->m.file_mode &
378 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
379 server->m.dir_mode = (server->m.dir_mode &
380 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
382 #ifdef CONFIG_NCPFS_NLS
383 /* load the default NLS charsets */
384 server->nls_charsets.codepage[0] = 0;
385 server->nls_charsets.iocharset[0] = 0;
386 server->nls_vol = load_nls_default();
387 server->nls_io = load_nls_default();
388 #endif /* CONFIG_NCPFS_NLS */
390 server->packet_size = NCP_PACKET_SIZE;
391 server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
392 if (server->packet == NULL)
393 goto out_no_packet;
395 ncp_lock_server(server);
396 error = ncp_connect(server);
397 ncp_unlock_server(server);
398 if (error < 0)
399 goto out_no_connect;
400 DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
402 #ifdef CONFIG_NCPFS_PACKET_SIGNING
403 if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
404 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
406 if (options != NCP_DEFAULT_OPTIONS)
408 if (ncp_negotiate_size_and_options(server,
409 NCP_DEFAULT_BUFSIZE,
410 options & 2,
411 &(server->buffer_size), &options) != 0)
414 goto out_no_bufsize;
417 if (options & 2)
418 server->sign_wanted = 1;
420 else
421 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
422 if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
423 &(server->buffer_size)) != 0)
424 goto out_no_bufsize;
425 DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);
427 ncp_init_root(server, &finfo);
428 server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS;
429 root_inode = ncp_iget(sb, &finfo);
430 if (!root_inode)
431 goto out_no_root;
432 DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
433 server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL);
434 if (!sb->s_root)
435 goto out_no_root;
436 server->root_dentry->d_op = &ncp_dentry_operations;
437 unlock_super(sb);
438 return sb;
440 out_no_root:
441 printk(KERN_ERR "ncp_read_super: get root inode failed\n");
442 iput(root_inode);
443 goto out_disconnect;
444 out_no_bufsize:
445 printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
446 out_disconnect:
447 ncp_lock_server(server);
448 ncp_disconnect(server);
449 ncp_unlock_server(server);
450 goto out_free_packet;
451 out_no_connect:
452 printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
453 out_free_packet:
454 ncp_kfree_s(server->packet, server->packet_size);
455 goto out_free_server;
456 out_no_packet:
457 printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
458 out_free_server:
459 #ifdef CONFIG_NCPFS_NLS
460 unload_nls(server->nls_io);
461 unload_nls(server->nls_vol);
462 #endif
463 ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
464 goto out_unlock;
465 out_no_server:
466 printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
467 out_unlock:
468 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
470 * The previously used put_filp(ncp_filp); was bogous, since
471 * it doesn't proper unlocking.
473 fput(ncp_filp);
474 unlock_super(sb);
475 goto out;
477 out_bad_file2:
478 fput(ncp_filp);
479 out_bad_file:
480 printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
481 goto out;
482 out_bad_mount:
483 printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
484 NCP_MOUNT_VERSION);
485 goto out;
486 out_no_data:
487 printk(KERN_ERR "ncp_read_super: missing data argument\n");
488 out:
489 sb->s_dev = 0;
490 MOD_DEC_USE_COUNT;
491 return NULL;
494 static void ncp_put_super(struct super_block *sb)
496 struct ncp_server *server = NCP_SBP(sb);
498 ncp_lock_server(server);
499 ncp_disconnect(server);
500 ncp_unlock_server(server);
502 #ifdef CONFIG_NCPFS_NLS
503 /* unload the NLS charsets */
504 if (server->nls_vol)
506 unload_nls(server->nls_vol);
507 server->nls_vol = NULL;
509 if (server->nls_io)
511 unload_nls(server->nls_io);
512 server->nls_io = NULL;
514 #endif /* CONFIG_NCPFS_NLS */
516 fput(server->ncp_filp);
517 kill_proc(server->m.wdog_pid, SIGTERM, 1);
519 if (server->priv.data)
520 ncp_kfree_s(server->priv.data, server->priv.len);
521 if (server->auth.object_name)
522 ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
523 ncp_kfree_s(server->packet, server->packet_size);
525 ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
527 MOD_DEC_USE_COUNT;
530 static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
532 struct statfs tmp;
534 /* We cannot say how much disk space is left on a mounted
535 NetWare Server, because free space is distributed over
536 volumes, and the current user might have disk quotas. So
537 free space is not that simple to determine. Our decision
538 here is to err conservatively. */
540 tmp.f_type = NCP_SUPER_MAGIC;
541 tmp.f_bsize = 512;
542 tmp.f_blocks = 0;
543 tmp.f_bfree = 0;
544 tmp.f_bavail = 0;
545 tmp.f_files = -1;
546 tmp.f_ffree = -1;
547 tmp.f_namelen = 12;
548 return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
551 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
553 struct inode *inode = dentry->d_inode;
554 int result = 0;
555 int info_mask;
556 struct nw_modify_dos_info info;
557 struct ncp_server *server;
559 result = -EIO;
561 server = NCP_SERVER(inode);
562 if ((!server) || !ncp_conn_valid(server))
563 goto out;
565 result = inode_change_ok(inode, attr);
566 if (result < 0)
567 goto out;
569 result = -EPERM;
570 if (((attr->ia_valid & ATTR_UID) &&
571 (attr->ia_uid != server->m.uid)))
572 goto out;
574 if (((attr->ia_valid & ATTR_GID) &&
575 (attr->ia_gid != server->m.gid)))
576 goto out;
578 if (((attr->ia_valid & ATTR_MODE) &&
579 (attr->ia_mode &
580 ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
581 goto out;
583 info_mask = 0;
584 memset(&info, 0, sizeof(info));
586 #if 1
587 if ((attr->ia_valid & ATTR_MODE) != 0)
589 if (S_ISDIR(inode->i_mode)) {
590 umode_t newmode;
592 info_mask |= DM_ATTRIBUTES;
593 newmode = attr->ia_mode;
594 newmode &= NCP_SERVER(inode)->m.dir_mode;
596 if (newmode & 0222)
597 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
598 else
599 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
600 } else if (!S_ISREG(inode->i_mode))
602 return -EPERM;
604 else
606 umode_t newmode;
607 #ifdef CONFIG_NCPFS_EXTRAS
608 int extras;
610 extras = server->m.flags & NCP_MOUNT_EXTRAS;
611 #endif
612 info_mask |= DM_ATTRIBUTES;
613 newmode=attr->ia_mode;
614 #ifdef CONFIG_NCPFS_EXTRAS
615 if (!extras)
616 #endif
617 newmode &= server->m.file_mode;
619 if (newmode & 0222) /* any write bit set */
621 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
623 else
625 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
627 #ifdef CONFIG_NCPFS_EXTRAS
628 if (extras) {
629 if (newmode & 0111) /* any execute bit set */
630 info.attributes |= aSHARED | aSYSTEM;
631 /* read for group/world and not in default file_mode */
632 else if (newmode & ~server->m.file_mode & 0444)
633 info.attributes |= aSHARED;
635 #endif
638 #endif
640 if ((attr->ia_valid & ATTR_CTIME) != 0) {
641 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
642 ncp_date_unix2dos(attr->ia_ctime,
643 &(info.creationTime), &(info.creationDate));
644 info.creationTime = le16_to_cpu(info.creationTime);
645 info.creationDate = le16_to_cpu(info.creationDate);
647 if ((attr->ia_valid & ATTR_MTIME) != 0) {
648 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
649 ncp_date_unix2dos(attr->ia_mtime,
650 &(info.modifyTime), &(info.modifyDate));
651 info.modifyTime = le16_to_cpu(info.modifyTime);
652 info.modifyDate = le16_to_cpu(info.modifyDate);
654 if ((attr->ia_valid & ATTR_ATIME) != 0) {
655 __u16 dummy;
656 info_mask |= (DM_LAST_ACCESS_DATE);
657 ncp_date_unix2dos(attr->ia_ctime,
658 &(dummy), &(info.lastAccessDate));
659 info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
661 if (info_mask != 0) {
662 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
663 inode, info_mask, &info);
664 if (result != 0) {
665 result = -EACCES;
667 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
668 /* NetWare seems not to allow this. I
669 do not know why. So, just tell the
670 user everything went fine. This is
671 a terrible hack, but I do not know
672 how to do this correctly. */
673 result = 0;
676 #ifdef CONFIG_NCPFS_STRONG
677 if ((!result) && (info_mask & DM_ATTRIBUTES))
678 NCP_FINFO(inode)->nwattr = info.attributes;
679 #endif
681 if ((attr->ia_valid & ATTR_SIZE) != 0) {
682 int written;
684 DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
685 attr->ia_size);
687 if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
688 return -EACCES;
690 ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
691 attr->ia_size, 0, "", &written);
693 /* According to ndir, the changes only take effect after
694 closing the file */
695 result = ncp_make_closed(inode);
697 ncp_invalid_dir_cache(dentry->d_parent->d_inode);
698 out:
699 return result;
702 #ifdef DEBUG_NCP_MALLOC
703 int ncp_malloced;
704 int ncp_current_malloced;
705 #endif
707 static struct file_system_type ncp_fs_type = {
708 "ncpfs",
709 0 /* FS_NO_DCACHE doesn't work correctly */,
710 ncp_read_super,
711 NULL
714 __initfunc(int init_ncp_fs(void))
716 return register_filesystem(&ncp_fs_type);
719 #ifdef MODULE
720 EXPORT_NO_SYMBOLS;
722 int init_module(void)
724 DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
726 init_MUTEX(&read_sem);
727 read_nwinfo = NULL;
729 #ifdef DEBUG_NCP_MALLOC
730 ncp_malloced = 0;
731 ncp_current_malloced = 0;
732 #endif
733 ncp_init_dir_cache();
735 return init_ncp_fs();
738 void cleanup_module(void)
740 DPRINTK(KERN_DEBUG "ncpfs: cleanup_module called\n");
741 ncp_free_dir_cache();
742 unregister_filesystem(&ncp_fs_type);
743 #ifdef DEBUG_NCP_MALLOC
744 printk(KERN_DEBUG "ncp_malloced: %d\n", ncp_malloced);
745 printk(KERN_DEBUG "ncp_current_malloced: %d\n", ncp_current_malloced);
746 #endif
749 #endif