Import 2.4.0-test2pre6
[davej-history.git] / fs / ncpfs / inode.c
blobe885aed47bf36d263b456eb175beee098a4cb13c
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_delete_inode(struct inode *);
35 static void ncp_put_super(struct super_block *);
36 static int ncp_statfs(struct super_block *, struct statfs *);
38 static struct super_operations ncp_sops =
40 put_inode: force_delete,
41 delete_inode: ncp_delete_inode,
42 put_super: ncp_put_super,
43 statfs: ncp_statfs,
46 extern struct dentry_operations ncp_dentry_operations;
47 #ifdef CONFIG_NCPFS_EXTRAS
48 extern struct address_space_operations ncp_symlink_aops;
49 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
50 #endif
53 * Fill in the ncpfs-specific information in the inode.
55 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
57 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
58 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
59 NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
61 #ifdef CONFIG_NCPFS_STRONG
62 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
63 #endif
64 NCP_FINFO(inode)->opened = nwinfo->opened;
65 NCP_FINFO(inode)->access = nwinfo->access;
66 NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
67 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
68 sizeof(nwinfo->file_handle));
69 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
70 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
71 NCP_FINFO(inode)->dirEntNum);
74 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
76 struct nw_info_struct *nwi = &nwinfo->i;
77 struct ncp_server *server = NCP_SERVER(inode);
79 if (!NCP_FINFO(inode)->opened) {
80 #ifdef CONFIG_NCPFS_STRONG
81 NCP_FINFO(inode)->nwattr = nwi->attributes;
82 #endif
83 if (nwi->attributes & aDIR) {
84 inode->i_mode = server->m.dir_mode;
85 inode->i_size = NCP_BLOCK_SIZE;
86 } else {
87 inode->i_mode = server->m.file_mode;
88 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
89 #ifdef CONFIG_NCPFS_EXTRAS
90 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
91 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
92 case aHIDDEN:
93 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
94 if ( /* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
95 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
96 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
97 break;
100 /* FALLTHROUGH */
101 case 0:
102 if (server->m.flags & NCP_MOUNT_EXTRAS)
103 inode->i_mode |= 0444;
104 break;
105 case aSYSTEM:
106 if (server->m.flags & NCP_MOUNT_EXTRAS)
107 inode->i_mode |= (inode->i_mode >> 2) & 0111;
108 break;
109 /* case aSYSTEM|aHIDDEN: */
110 default:
111 /* reserved combination */
112 break;
115 #endif
117 if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
119 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
121 inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
122 le16_to_cpu(nwi->modifyDate));
123 inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
124 le16_to_cpu(nwi->creationDate));
125 inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate));
127 NCP_FINFO(inode)->DosDirNum = nwi->DosDirNum;
128 NCP_FINFO(inode)->dirEntNum = nwi->dirEntNum;
129 NCP_FINFO(inode)->volNumber = nwi->volNumber;
133 * Fill in the inode based on the ncp_entry_info structure.
135 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
137 struct nw_info_struct *nwi = &nwinfo->i;
138 struct ncp_server *server = NCP_SERVER(inode);
140 if (nwi->attributes & aDIR) {
141 inode->i_mode = server->m.dir_mode;
142 /* for directories dataStreamSize seems to be some
143 Object ID ??? */
144 inode->i_size = NCP_BLOCK_SIZE;
145 } else {
146 inode->i_mode = server->m.file_mode;
147 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
148 #ifdef CONFIG_NCPFS_EXTRAS
149 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
150 && (nwi->attributes & aSHARED)) {
151 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
152 case aHIDDEN:
153 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
154 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
155 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
156 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
157 break;
160 /* FALLTHROUGH */
161 case 0:
162 if (server->m.flags & NCP_MOUNT_EXTRAS)
163 inode->i_mode |= 0444;
164 break;
165 case aSYSTEM:
166 if (server->m.flags & NCP_MOUNT_EXTRAS)
167 inode->i_mode |= (inode->i_mode >> 2) & 0111;
168 break;
169 /* case aSYSTEM|aHIDDEN: */
170 default:
171 /* reserved combination */
172 break;
175 #endif
177 if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
179 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
181 inode->i_nlink = 1;
182 inode->i_uid = server->m.uid;
183 inode->i_gid = server->m.gid;
184 inode->i_rdev = 0;
185 inode->i_blksize = NCP_BLOCK_SIZE;
187 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
189 inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
190 le16_to_cpu(nwi->modifyDate));
191 inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
192 le16_to_cpu(nwi->creationDate));
193 inode->i_atime = ncp_date_dos2unix(0,
194 le16_to_cpu(nwi->lastAccessDate));
195 ncp_update_inode(inode, nwinfo);
198 static struct inode_operations ncp_symlink_inode_operations = {
199 readlink: page_readlink,
200 follow_link: page_follow_link,
201 setattr: ncp_notify_change,
205 * Get a new inode.
207 struct inode *
208 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
210 struct inode *inode;
212 if (info == NULL) {
213 printk(KERN_ERR "ncp_iget: info is NULL\n");
214 return NULL;
217 inode = get_empty_inode();
218 if (inode) {
219 inode->i_sb = sb;
220 inode->i_dev = sb->s_dev;
221 inode->i_ino = info->ino;
222 ncp_set_attr(inode, info);
223 if (S_ISREG(inode->i_mode)) {
224 inode->i_op = &ncp_file_inode_operations;
225 inode->i_fop = &ncp_file_operations;
226 } else if (S_ISDIR(inode->i_mode)) {
227 inode->i_op = &ncp_dir_inode_operations;
228 inode->i_fop = &ncp_dir_operations;
229 #ifdef CONFIG_NCPFS_EXTRAS
230 } else if (S_ISLNK(inode->i_mode)) {
231 inode->i_op = &ncp_symlink_inode_operations;
232 inode->i_data.a_ops = &ncp_symlink_aops;
233 #endif
235 insert_inode_hash(inode);
236 } else
237 printk(KERN_ERR "ncp_iget: iget failed!\n");
238 return inode;
241 static void
242 ncp_delete_inode(struct inode *inode)
244 if (S_ISDIR(inode->i_mode)) {
245 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
248 if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
249 /* We can't do anything but complain. */
250 printk(KERN_ERR "ncp_delete_inode: could not close\n");
252 clear_inode(inode);
255 struct super_block *
256 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
258 struct ncp_mount_data_kernel data;
259 struct ncp_server *server;
260 struct file *ncp_filp;
261 struct inode *root_inode;
262 kdev_t dev = sb->s_dev;
263 int error;
264 #ifdef CONFIG_NCPFS_PACKET_SIGNING
265 int options;
266 #endif
267 struct ncp_entry_info finfo;
269 if (raw_data == NULL)
270 goto out_no_data;
271 switch (*(int*)raw_data) {
272 case NCP_MOUNT_VERSION:
274 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
276 data.flags = md->flags;
277 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
278 data.mounted_uid = md->mounted_uid;
279 data.wdog_pid = md->wdog_pid;
280 data.ncp_fd = md->ncp_fd;
281 data.time_out = md->time_out;
282 data.retry_count = md->retry_count;
283 data.uid = md->uid;
284 data.gid = md->gid;
285 data.file_mode = md->file_mode;
286 data.dir_mode = md->dir_mode;
287 memcpy(data.mounted_vol, md->mounted_vol,
288 NCP_VOLNAME_LEN+1);
290 break;
291 case NCP_MOUNT_VERSION_V4:
293 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
295 data.flags = md->flags;
296 data.int_flags = 0;
297 data.mounted_uid = md->mounted_uid;
298 data.wdog_pid = md->wdog_pid;
299 data.ncp_fd = md->ncp_fd;
300 data.time_out = md->time_out;
301 data.retry_count = md->retry_count;
302 data.uid = md->uid;
303 data.gid = md->gid;
304 data.file_mode = md->file_mode;
305 data.dir_mode = md->dir_mode;
306 data.mounted_vol[0] = 0;
308 break;
309 default:
310 goto out_bad_mount;
312 ncp_filp = fget(data.ncp_fd);
313 if (!ncp_filp)
314 goto out_bad_file;
315 if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
316 goto out_bad_file2;
318 sb->s_blocksize = 1024; /* Eh... Is this correct? */
319 sb->s_blocksize_bits = 10;
320 sb->s_magic = NCP_SUPER_MAGIC;
321 sb->s_dev = dev;
322 sb->s_op = &ncp_sops;
324 server = NCP_SBP(sb);
325 memset(server, 0, sizeof(*server));
327 server->ncp_filp = ncp_filp;
328 /* server->lock = 0; */
329 init_MUTEX(&server->sem);
330 server->packet = NULL;
331 /* server->buffer_size = 0; */
332 /* server->conn_status = 0; */
333 /* server->root_dentry = NULL; */
334 /* server->root_setuped = 0; */
335 #ifdef CONFIG_NCPFS_PACKET_SIGNING
336 /* server->sign_wanted = 0; */
337 /* server->sign_active = 0; */
338 #endif
339 server->auth.auth_type = NCP_AUTH_NONE;
340 /* server->auth.object_name_len = 0; */
341 /* server->auth.object_name = NULL; */
342 /* server->auth.object_type = 0; */
343 /* server->priv.len = 0; */
344 /* server->priv.data = NULL; */
346 server->m = data;
347 /* Althought anything producing this is buggy, it happens
348 now because of PATH_MAX changes.. */
349 if (server->m.time_out < 1) {
350 server->m.time_out = 10;
351 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
353 server->m.time_out = server->m.time_out * HZ / 100;
354 server->m.file_mode = (server->m.file_mode &
355 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
356 server->m.dir_mode = (server->m.dir_mode &
357 (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
359 #ifdef CONFIG_NCPFS_NLS
360 /* load the default NLS charsets */
361 server->nls_vol = load_nls_default();
362 server->nls_io = load_nls_default();
363 #endif /* CONFIG_NCPFS_NLS */
365 server->dentry_ttl = 0; /* no caching */
367 server->packet_size = NCP_PACKET_SIZE;
368 server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
369 if (server->packet == NULL)
370 goto out_no_packet;
372 ncp_lock_server(server);
373 error = ncp_connect(server);
374 ncp_unlock_server(server);
375 if (error < 0)
376 goto out_no_connect;
377 DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
379 #ifdef CONFIG_NCPFS_PACKET_SIGNING
380 if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
381 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
383 if (options != NCP_DEFAULT_OPTIONS)
385 if (ncp_negotiate_size_and_options(server,
386 NCP_DEFAULT_BUFSIZE,
387 options & 2,
388 &(server->buffer_size), &options) != 0)
391 goto out_no_bufsize;
394 if (options & 2)
395 server->sign_wanted = 1;
397 else
398 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
399 if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
400 &(server->buffer_size)) != 0)
401 goto out_no_bufsize;
402 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
404 memset(&finfo, 0, sizeof(finfo));
405 finfo.i.attributes = aDIR;
406 finfo.i.dataStreamSize = NCP_BLOCK_SIZE;
407 finfo.i.dirEntNum = 0;
408 finfo.i.DosDirNum = 0;
409 #ifdef CONFIG_NCPFS_SMALLDOS
410 finfo.i.NSCreator = NW_NS_DOS;
411 #endif
412 finfo.i.volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */
413 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
414 finfo.i.creationTime = finfo.i.modifyTime
415 = cpu_to_le16(0x0000);
416 finfo.i.creationDate = finfo.i.modifyDate
417 = finfo.i.lastAccessDate
418 = cpu_to_le16(0x0C21);
419 finfo.i.nameLen = 0;
420 finfo.i.entryName[0] = '\0';
422 finfo.opened = 0;
423 finfo.ino = 2; /* tradition */
425 server->name_space[finfo.i.volNumber] = NW_NS_DOS;
426 root_inode = ncp_iget(sb, &finfo);
427 if (!root_inode)
428 goto out_no_root;
429 DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
430 sb->s_root = d_alloc_root(root_inode);
431 if (!sb->s_root)
432 goto out_no_root;
433 sb->s_root->d_op = &ncp_dentry_operations;
434 return sb;
436 out_no_root:
437 printk(KERN_ERR "ncp_read_super: get root inode failed\n");
438 iput(root_inode);
439 goto out_disconnect;
440 out_no_bufsize:
441 printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
442 out_disconnect:
443 ncp_lock_server(server);
444 ncp_disconnect(server);
445 ncp_unlock_server(server);
446 goto out_free_packet;
447 out_no_connect:
448 printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
449 out_free_packet:
450 ncp_kfree_s(server->packet, server->packet_size);
451 goto out_free_server;
452 out_no_packet:
453 printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
454 out_free_server:
455 #ifdef CONFIG_NCPFS_NLS
456 unload_nls(server->nls_io);
457 unload_nls(server->nls_vol);
458 #endif
459 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
461 * The previously used put_filp(ncp_filp); was bogous, since
462 * it doesn't proper unlocking.
464 fput(ncp_filp);
465 goto out;
467 out_bad_file2:
468 fput(ncp_filp);
469 out_bad_file:
470 printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
471 goto out;
472 out_bad_mount:
473 printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
474 NCP_MOUNT_VERSION);
475 goto out;
476 out_no_data:
477 printk(KERN_ERR "ncp_read_super: missing data argument\n");
478 out:
479 return NULL;
482 static void ncp_put_super(struct super_block *sb)
484 struct ncp_server *server = NCP_SBP(sb);
486 ncp_lock_server(server);
487 ncp_disconnect(server);
488 ncp_unlock_server(server);
490 #ifdef CONFIG_NCPFS_NLS
491 /* unload the NLS charsets */
492 if (server->nls_vol)
494 unload_nls(server->nls_vol);
495 server->nls_vol = NULL;
497 if (server->nls_io)
499 unload_nls(server->nls_io);
500 server->nls_io = NULL;
502 #endif /* CONFIG_NCPFS_NLS */
504 fput(server->ncp_filp);
505 kill_proc(server->m.wdog_pid, SIGTERM, 1);
507 if (server->priv.data)
508 ncp_kfree_s(server->priv.data, server->priv.len);
509 if (server->auth.object_name)
510 ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
511 ncp_kfree_s(server->packet, server->packet_size);
515 static int ncp_statfs(struct super_block *sb, struct statfs *buf)
517 /* We cannot say how much disk space is left on a mounted
518 NetWare Server, because free space is distributed over
519 volumes, and the current user might have disk quotas. So
520 free space is not that simple to determine. Our decision
521 here is to err conservatively. */
523 buf->f_type = NCP_SUPER_MAGIC;
524 buf->f_bsize = NCP_BLOCK_SIZE;
525 buf->f_blocks = 0;
526 buf->f_bfree = 0;
527 buf->f_bavail = 0;
528 buf->f_namelen = 12;
529 return 0;
532 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
534 struct inode *inode = dentry->d_inode;
535 int result = 0;
536 int info_mask;
537 struct nw_modify_dos_info info;
538 struct ncp_server *server;
540 result = -EIO;
542 server = NCP_SERVER(inode);
543 if ((!server) || !ncp_conn_valid(server))
544 goto out;
546 /* ageing the dentry to force validation */
547 ncp_age_dentry(server, dentry);
549 result = inode_change_ok(inode, attr);
550 if (result < 0)
551 goto out;
553 result = -EPERM;
554 if (((attr->ia_valid & ATTR_UID) &&
555 (attr->ia_uid != server->m.uid)))
556 goto out;
558 if (((attr->ia_valid & ATTR_GID) &&
559 (attr->ia_gid != server->m.gid)))
560 goto out;
562 if (((attr->ia_valid & ATTR_MODE) &&
563 (attr->ia_mode &
564 ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
565 goto out;
567 info_mask = 0;
568 memset(&info, 0, sizeof(info));
570 #if 1
571 if ((attr->ia_valid & ATTR_MODE) != 0)
573 if (S_ISDIR(inode->i_mode)) {
574 umode_t newmode;
576 info_mask |= DM_ATTRIBUTES;
577 newmode = attr->ia_mode;
578 newmode &= NCP_SERVER(inode)->m.dir_mode;
580 if (newmode & 0222)
581 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
582 else
583 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
584 } else if (!S_ISREG(inode->i_mode))
586 return -EPERM;
588 else
590 umode_t newmode;
591 #ifdef CONFIG_NCPFS_EXTRAS
592 int extras;
594 extras = server->m.flags & NCP_MOUNT_EXTRAS;
595 #endif
596 info_mask |= DM_ATTRIBUTES;
597 newmode=attr->ia_mode;
598 #ifdef CONFIG_NCPFS_EXTRAS
599 if (!extras)
600 #endif
601 newmode &= server->m.file_mode;
603 if (newmode & 0222) /* any write bit set */
605 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
607 else
609 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
611 #ifdef CONFIG_NCPFS_EXTRAS
612 if (extras) {
613 if (newmode & 0111) /* any execute bit set */
614 info.attributes |= aSHARED | aSYSTEM;
615 /* read for group/world and not in default file_mode */
616 else if (newmode & ~server->m.file_mode & 0444)
617 info.attributes |= aSHARED;
619 #endif
622 #endif
624 if ((attr->ia_valid & ATTR_CTIME) != 0) {
625 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
626 ncp_date_unix2dos(attr->ia_ctime,
627 &(info.creationTime), &(info.creationDate));
628 info.creationTime = le16_to_cpu(info.creationTime);
629 info.creationDate = le16_to_cpu(info.creationDate);
631 if ((attr->ia_valid & ATTR_MTIME) != 0) {
632 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
633 ncp_date_unix2dos(attr->ia_mtime,
634 &(info.modifyTime), &(info.modifyDate));
635 info.modifyTime = le16_to_cpu(info.modifyTime);
636 info.modifyDate = le16_to_cpu(info.modifyDate);
638 if ((attr->ia_valid & ATTR_ATIME) != 0) {
639 __u16 dummy;
640 info_mask |= (DM_LAST_ACCESS_DATE);
641 ncp_date_unix2dos(attr->ia_ctime,
642 &(dummy), &(info.lastAccessDate));
643 info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
645 if (info_mask != 0) {
646 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
647 inode, info_mask, &info);
648 if (result != 0) {
649 result = -EACCES;
651 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
652 /* NetWare seems not to allow this. I
653 do not know why. So, just tell the
654 user everything went fine. This is
655 a terrible hack, but I do not know
656 how to do this correctly. */
657 result = 0;
660 #ifdef CONFIG_NCPFS_STRONG
661 if ((!result) && (info_mask & DM_ATTRIBUTES))
662 NCP_FINFO(inode)->nwattr = info.attributes;
663 #endif
665 if ((attr->ia_valid & ATTR_SIZE) != 0) {
666 int written;
668 DPRINTK("ncpfs: trying to change size to %ld\n",
669 attr->ia_size);
671 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
672 return -EACCES;
674 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
675 attr->ia_size, 0, "", &written);
677 /* According to ndir, the changes only take effect after
678 closing the file */
679 result = ncp_make_closed(inode);
680 if (!result)
681 vmtruncate(inode, attr->ia_size);
683 out:
684 return result;
687 #ifdef DEBUG_NCP_MALLOC
688 int ncp_malloced;
689 int ncp_current_malloced;
690 #endif
692 static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
694 static int __init init_ncp_fs(void)
696 DPRINTK("ncpfs: init_module called\n");
698 #ifdef DEBUG_NCP_MALLOC
699 ncp_malloced = 0;
700 ncp_current_malloced = 0;
701 #endif
702 return register_filesystem(&ncp_fs_type);
705 static void __exit exit_ncp_fs(void)
707 DPRINTK("ncpfs: cleanup_module called\n");
708 unregister_filesystem(&ncp_fs_type);
709 #ifdef DEBUG_NCP_MALLOC
710 PRINTK("ncp_malloced: %d\n", ncp_malloced);
711 PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
712 #endif
715 EXPORT_NO_SYMBOLS;
717 module_init(init_ncp_fs)
718 module_exit(exit_ncp_fs)