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
12 #include <linux/module.h>
14 #include <asm/system.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
18 #include <linux/time.h>
19 #include <linux/kernel.h>
21 #include <linux/string.h>
22 #include <linux/stat.h>
23 #include <linux/errno.h>
24 #include <linux/file.h>
25 #include <linux/fcntl.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/init.h>
29 #include <linux/smp_lock.h>
30 #include <linux/vfs.h>
31 #include <linux/mount.h>
32 #include <linux/seq_file.h>
34 #include <linux/ncp_fs.h>
38 #include "ncplib_kernel.h"
41 #define NCP_DEFAULT_FILE_MODE 0600
42 #define NCP_DEFAULT_DIR_MODE 0700
43 #define NCP_DEFAULT_TIME_OUT 10
44 #define NCP_DEFAULT_RETRY_COUNT 20
46 static void ncp_evict_inode(struct inode
*);
47 static void ncp_put_super(struct super_block
*);
48 static int ncp_statfs(struct dentry
*, struct kstatfs
*);
49 static int ncp_show_options(struct seq_file
*, struct vfsmount
*);
51 static struct kmem_cache
* ncp_inode_cachep
;
53 static struct inode
*ncp_alloc_inode(struct super_block
*sb
)
55 struct ncp_inode_info
*ei
;
56 ei
= (struct ncp_inode_info
*)kmem_cache_alloc(ncp_inode_cachep
, GFP_KERNEL
);
59 return &ei
->vfs_inode
;
62 static void ncp_destroy_inode(struct inode
*inode
)
64 kmem_cache_free(ncp_inode_cachep
, NCP_FINFO(inode
));
67 static void init_once(void *foo
)
69 struct ncp_inode_info
*ei
= (struct ncp_inode_info
*) foo
;
71 mutex_init(&ei
->open_mutex
);
72 inode_init_once(&ei
->vfs_inode
);
75 static int init_inodecache(void)
77 ncp_inode_cachep
= kmem_cache_create("ncp_inode_cache",
78 sizeof(struct ncp_inode_info
),
79 0, (SLAB_RECLAIM_ACCOUNT
|
82 if (ncp_inode_cachep
== NULL
)
87 static void destroy_inodecache(void)
89 kmem_cache_destroy(ncp_inode_cachep
);
92 static int ncp_remount(struct super_block
*sb
, int *flags
, char* data
)
94 *flags
|= MS_NODIRATIME
;
98 static const struct super_operations ncp_sops
=
100 .alloc_inode
= ncp_alloc_inode
,
101 .destroy_inode
= ncp_destroy_inode
,
102 .drop_inode
= generic_delete_inode
,
103 .evict_inode
= ncp_evict_inode
,
104 .put_super
= ncp_put_super
,
105 .statfs
= ncp_statfs
,
106 .remount_fs
= ncp_remount
,
107 .show_options
= ncp_show_options
,
111 * Fill in the ncpfs-specific information in the inode.
113 static void ncp_update_dirent(struct inode
*inode
, struct ncp_entry_info
*nwinfo
)
115 NCP_FINFO(inode
)->DosDirNum
= nwinfo
->i
.DosDirNum
;
116 NCP_FINFO(inode
)->dirEntNum
= nwinfo
->i
.dirEntNum
;
117 NCP_FINFO(inode
)->volNumber
= nwinfo
->volume
;
120 void ncp_update_inode(struct inode
*inode
, struct ncp_entry_info
*nwinfo
)
122 ncp_update_dirent(inode
, nwinfo
);
123 NCP_FINFO(inode
)->nwattr
= nwinfo
->i
.attributes
;
124 NCP_FINFO(inode
)->access
= nwinfo
->access
;
125 memcpy(NCP_FINFO(inode
)->file_handle
, nwinfo
->file_handle
,
126 sizeof(nwinfo
->file_handle
));
127 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
128 nwinfo
->i
.entryName
, NCP_FINFO(inode
)->volNumber
,
129 NCP_FINFO(inode
)->dirEntNum
);
132 static void ncp_update_dates(struct inode
*inode
, struct nw_info_struct
*nwi
)
134 /* NFS namespace mode overrides others if it's set. */
135 DPRINTK(KERN_DEBUG
"ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
136 nwi
->entryName
, nwi
->nfs
.mode
);
138 inode
->i_mode
= nwi
->nfs
.mode
;
141 inode
->i_blocks
= (inode
->i_size
+ NCP_BLOCK_SIZE
- 1) >> NCP_BLOCK_SHIFT
;
143 inode
->i_mtime
.tv_sec
= ncp_date_dos2unix(nwi
->modifyTime
, nwi
->modifyDate
);
144 inode
->i_ctime
.tv_sec
= ncp_date_dos2unix(nwi
->creationTime
, nwi
->creationDate
);
145 inode
->i_atime
.tv_sec
= ncp_date_dos2unix(0, nwi
->lastAccessDate
);
146 inode
->i_atime
.tv_nsec
= 0;
147 inode
->i_mtime
.tv_nsec
= 0;
148 inode
->i_ctime
.tv_nsec
= 0;
151 static void ncp_update_attrs(struct inode
*inode
, struct ncp_entry_info
*nwinfo
)
153 struct nw_info_struct
*nwi
= &nwinfo
->i
;
154 struct ncp_server
*server
= NCP_SERVER(inode
);
156 if (nwi
->attributes
& aDIR
) {
157 inode
->i_mode
= server
->m
.dir_mode
;
158 /* for directories dataStreamSize seems to be some
160 inode
->i_size
= NCP_BLOCK_SIZE
;
162 inode
->i_mode
= server
->m
.file_mode
;
163 inode
->i_size
= le32_to_cpu(nwi
->dataStreamSize
);
164 #ifdef CONFIG_NCPFS_EXTRAS
165 if ((server
->m
.flags
& (NCP_MOUNT_EXTRAS
|NCP_MOUNT_SYMLINKS
))
166 && (nwi
->attributes
& aSHARED
)) {
167 switch (nwi
->attributes
& (aHIDDEN
|aSYSTEM
)) {
169 if (server
->m
.flags
& NCP_MOUNT_SYMLINKS
) {
170 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
171 && */ (inode
->i_size
<= NCP_MAX_SYMLINK_SIZE
)) {
172 inode
->i_mode
= (inode
->i_mode
& ~S_IFMT
) | S_IFLNK
;
173 NCP_FINFO(inode
)->flags
|= NCPI_KLUDGE_SYMLINK
;
179 if (server
->m
.flags
& NCP_MOUNT_EXTRAS
)
180 inode
->i_mode
|= S_IRUGO
;
183 if (server
->m
.flags
& NCP_MOUNT_EXTRAS
)
184 inode
->i_mode
|= (inode
->i_mode
>> 2) & S_IXUGO
;
186 /* case aSYSTEM|aHIDDEN: */
188 /* reserved combination */
194 if (nwi
->attributes
& aRONLY
) inode
->i_mode
&= ~S_IWUGO
;
197 void ncp_update_inode2(struct inode
* inode
, struct ncp_entry_info
*nwinfo
)
199 NCP_FINFO(inode
)->flags
= 0;
200 if (!atomic_read(&NCP_FINFO(inode
)->opened
)) {
201 NCP_FINFO(inode
)->nwattr
= nwinfo
->i
.attributes
;
202 ncp_update_attrs(inode
, nwinfo
);
205 ncp_update_dates(inode
, &nwinfo
->i
);
206 ncp_update_dirent(inode
, nwinfo
);
210 * Fill in the inode based on the ncp_entry_info structure.
212 static void ncp_set_attr(struct inode
*inode
, struct ncp_entry_info
*nwinfo
)
214 struct ncp_server
*server
= NCP_SERVER(inode
);
216 NCP_FINFO(inode
)->flags
= 0;
218 ncp_update_attrs(inode
, nwinfo
);
220 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode
->i_mode
);
223 inode
->i_uid
= server
->m
.uid
;
224 inode
->i_gid
= server
->m
.gid
;
226 ncp_update_dates(inode
, &nwinfo
->i
);
227 ncp_update_inode(inode
, nwinfo
);
230 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
231 static const struct inode_operations ncp_symlink_inode_operations
= {
232 .readlink
= generic_readlink
,
233 .follow_link
= page_follow_link_light
,
234 .put_link
= page_put_link
,
235 .setattr
= ncp_notify_change
,
243 ncp_iget(struct super_block
*sb
, struct ncp_entry_info
*info
)
248 printk(KERN_ERR
"ncp_iget: info is NULL\n");
252 inode
= new_inode(sb
);
254 atomic_set(&NCP_FINFO(inode
)->opened
, info
->opened
);
256 inode
->i_ino
= info
->ino
;
257 ncp_set_attr(inode
, info
);
258 if (S_ISREG(inode
->i_mode
)) {
259 inode
->i_op
= &ncp_file_inode_operations
;
260 inode
->i_fop
= &ncp_file_operations
;
261 } else if (S_ISDIR(inode
->i_mode
)) {
262 inode
->i_op
= &ncp_dir_inode_operations
;
263 inode
->i_fop
= &ncp_dir_operations
;
264 #ifdef CONFIG_NCPFS_NFS_NS
265 } else if (S_ISCHR(inode
->i_mode
) || S_ISBLK(inode
->i_mode
) || S_ISFIFO(inode
->i_mode
) || S_ISSOCK(inode
->i_mode
)) {
266 init_special_inode(inode
, inode
->i_mode
,
267 new_decode_dev(info
->i
.nfs
.rdev
));
269 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
270 } else if (S_ISLNK(inode
->i_mode
)) {
271 inode
->i_op
= &ncp_symlink_inode_operations
;
272 inode
->i_data
.a_ops
= &ncp_symlink_aops
;
275 make_bad_inode(inode
);
277 insert_inode_hash(inode
);
279 printk(KERN_ERR
"ncp_iget: iget failed!\n");
284 ncp_evict_inode(struct inode
*inode
)
286 truncate_inode_pages(&inode
->i_data
, 0);
287 end_writeback(inode
);
289 if (S_ISDIR(inode
->i_mode
)) {
290 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode
->i_ino
);
293 if (ncp_make_closed(inode
) != 0) {
294 /* We can't do anything but complain. */
295 printk(KERN_ERR
"ncp_evict_inode: could not close\n");
299 static void ncp_stop_tasks(struct ncp_server
*server
) {
300 struct sock
* sk
= server
->ncp_sock
->sk
;
302 sk
->sk_error_report
= server
->error_report
;
303 sk
->sk_data_ready
= server
->data_ready
;
304 sk
->sk_write_space
= server
->write_space
;
305 del_timer_sync(&server
->timeout_tm
);
306 flush_scheduled_work();
309 static int ncp_show_options(struct seq_file
*seq
, struct vfsmount
*mnt
)
311 struct ncp_server
*server
= NCP_SBP(mnt
->mnt_sb
);
314 if (server
->m
.uid
!= 0)
315 seq_printf(seq
, ",uid=%u", server
->m
.uid
);
316 if (server
->m
.gid
!= 0)
317 seq_printf(seq
, ",gid=%u", server
->m
.gid
);
318 if (server
->m
.mounted_uid
!= 0)
319 seq_printf(seq
, ",owner=%u", server
->m
.mounted_uid
);
320 tmp
= server
->m
.file_mode
& S_IALLUGO
;
321 if (tmp
!= NCP_DEFAULT_FILE_MODE
)
322 seq_printf(seq
, ",mode=0%o", tmp
);
323 tmp
= server
->m
.dir_mode
& S_IALLUGO
;
324 if (tmp
!= NCP_DEFAULT_DIR_MODE
)
325 seq_printf(seq
, ",dirmode=0%o", tmp
);
326 if (server
->m
.time_out
!= NCP_DEFAULT_TIME_OUT
* HZ
/ 100) {
327 tmp
= server
->m
.time_out
* 100 / HZ
;
328 seq_printf(seq
, ",timeout=%u", tmp
);
330 if (server
->m
.retry_count
!= NCP_DEFAULT_RETRY_COUNT
)
331 seq_printf(seq
, ",retry=%u", server
->m
.retry_count
);
332 if (server
->m
.flags
!= 0)
333 seq_printf(seq
, ",flags=%lu", server
->m
.flags
);
334 if (server
->m
.wdog_pid
!= NULL
)
335 seq_printf(seq
, ",wdogpid=%u", pid_vnr(server
->m
.wdog_pid
));
340 static const struct ncp_option ncp_opts
[] = {
341 { "uid", OPT_INT
, 'u' },
342 { "gid", OPT_INT
, 'g' },
343 { "owner", OPT_INT
, 'o' },
344 { "mode", OPT_INT
, 'm' },
345 { "dirmode", OPT_INT
, 'd' },
346 { "timeout", OPT_INT
, 't' },
347 { "retry", OPT_INT
, 'r' },
348 { "flags", OPT_INT
, 'f' },
349 { "wdogpid", OPT_INT
, 'w' },
350 { "ncpfd", OPT_INT
, 'n' },
351 { "infofd", OPT_INT
, 'i' }, /* v5 */
352 { "version", OPT_INT
, 'v' },
355 static int ncp_parse_options(struct ncp_mount_data_kernel
*data
, char *options
) {
358 unsigned long optint
;
364 data
->mounted_uid
= 0;
365 data
->wdog_pid
= NULL
;
367 data
->time_out
= NCP_DEFAULT_TIME_OUT
;
368 data
->retry_count
= NCP_DEFAULT_RETRY_COUNT
;
371 data
->file_mode
= NCP_DEFAULT_FILE_MODE
;
372 data
->dir_mode
= NCP_DEFAULT_DIR_MODE
;
374 data
->mounted_vol
[0] = 0;
376 while ((optval
= ncp_getopt("ncpfs", &options
, ncp_opts
, NULL
, &optarg
, &optint
)) != 0) {
388 data
->mounted_uid
= optint
;
391 data
->file_mode
= optint
;
394 data
->dir_mode
= optint
;
397 data
->time_out
= optint
;
400 data
->retry_count
= optint
;
403 data
->flags
= optint
;
406 data
->wdog_pid
= find_get_pid(optint
);
409 data
->ncp_fd
= optint
;
412 data
->info_fd
= optint
;
416 if (optint
< NCP_MOUNT_VERSION_V4
)
418 if (optint
> NCP_MOUNT_VERSION_V5
)
427 put_pid(data
->wdog_pid
);
428 data
->wdog_pid
= NULL
;
432 static int ncp_fill_super(struct super_block
*sb
, void *raw_data
, int silent
)
434 struct ncp_mount_data_kernel data
;
435 struct ncp_server
*server
;
436 struct file
*ncp_filp
;
437 struct inode
*root_inode
;
438 struct inode
*sock_inode
;
442 #ifdef CONFIG_NCPFS_PACKET_SIGNING
445 struct ncp_entry_info finfo
;
447 data
.wdog_pid
= NULL
;
448 server
= kzalloc(sizeof(struct ncp_server
), GFP_KERNEL
);
451 sb
->s_fs_info
= server
;
454 if (raw_data
== NULL
)
456 switch (*(int*)raw_data
) {
457 case NCP_MOUNT_VERSION
:
459 struct ncp_mount_data
* md
= (struct ncp_mount_data
*)raw_data
;
461 data
.flags
= md
->flags
;
462 data
.int_flags
= NCP_IMOUNT_LOGGEDIN_POSSIBLE
;
463 data
.mounted_uid
= md
->mounted_uid
;
464 data
.wdog_pid
= find_get_pid(md
->wdog_pid
);
465 data
.ncp_fd
= md
->ncp_fd
;
466 data
.time_out
= md
->time_out
;
467 data
.retry_count
= md
->retry_count
;
470 data
.file_mode
= md
->file_mode
;
471 data
.dir_mode
= md
->dir_mode
;
473 memcpy(data
.mounted_vol
, md
->mounted_vol
,
477 case NCP_MOUNT_VERSION_V4
:
479 struct ncp_mount_data_v4
* md
= (struct ncp_mount_data_v4
*)raw_data
;
481 data
.flags
= md
->flags
;
483 data
.mounted_uid
= md
->mounted_uid
;
484 data
.wdog_pid
= find_get_pid(md
->wdog_pid
);
485 data
.ncp_fd
= md
->ncp_fd
;
486 data
.time_out
= md
->time_out
;
487 data
.retry_count
= md
->retry_count
;
490 data
.file_mode
= md
->file_mode
;
491 data
.dir_mode
= md
->dir_mode
;
493 data
.mounted_vol
[0] = 0;
498 if (memcmp(raw_data
, "vers", 4) == 0) {
499 error
= ncp_parse_options(&data
, raw_data
);
506 ncp_filp
= fget(data
.ncp_fd
);
510 sock_inode
= ncp_filp
->f_path
.dentry
->d_inode
;
511 if (!S_ISSOCK(sock_inode
->i_mode
))
513 sock
= SOCKET_I(sock_inode
);
517 if (sock
->type
== SOCK_STREAM
)
518 default_bufsize
= 0xF000;
520 default_bufsize
= 1024;
522 sb
->s_flags
|= MS_NODIRATIME
; /* probably even noatime */
523 sb
->s_maxbytes
= 0xFFFFFFFFU
;
524 sb
->s_blocksize
= 1024; /* Eh... Is this correct? */
525 sb
->s_blocksize_bits
= 10;
526 sb
->s_magic
= NCP_SUPER_MAGIC
;
527 sb
->s_op
= &ncp_sops
;
528 sb
->s_bdi
= &server
->bdi
;
530 server
= NCP_SBP(sb
);
531 memset(server
, 0, sizeof(*server
));
533 error
= bdi_setup_and_register(&server
->bdi
, "ncpfs", BDI_CAP_MAP_COPY
);
537 server
->ncp_filp
= ncp_filp
;
538 server
->ncp_sock
= sock
;
540 if (data
.info_fd
!= -1) {
541 struct socket
*info_sock
;
544 server
->info_filp
= fget(data
.info_fd
);
545 if (!server
->info_filp
)
548 sock_inode
= server
->info_filp
->f_path
.dentry
->d_inode
;
549 if (!S_ISSOCK(sock_inode
->i_mode
))
551 info_sock
= SOCKET_I(sock_inode
);
555 if (info_sock
->type
!= SOCK_STREAM
)
557 server
->info_sock
= info_sock
;
560 /* server->lock = 0; */
561 mutex_init(&server
->mutex
);
562 server
->packet
= NULL
;
563 /* server->buffer_size = 0; */
564 /* server->conn_status = 0; */
565 /* server->root_dentry = NULL; */
566 /* server->root_setuped = 0; */
567 #ifdef CONFIG_NCPFS_PACKET_SIGNING
568 /* server->sign_wanted = 0; */
569 /* server->sign_active = 0; */
571 server
->auth
.auth_type
= NCP_AUTH_NONE
;
572 /* server->auth.object_name_len = 0; */
573 /* server->auth.object_name = NULL; */
574 /* server->auth.object_type = 0; */
575 /* server->priv.len = 0; */
576 /* server->priv.data = NULL; */
579 /* Althought anything producing this is buggy, it happens
580 now because of PATH_MAX changes.. */
581 if (server
->m
.time_out
< 1) {
582 server
->m
.time_out
= 10;
583 printk(KERN_INFO
"You need to recompile your ncpfs utils..\n");
585 server
->m
.time_out
= server
->m
.time_out
* HZ
/ 100;
586 server
->m
.file_mode
= (server
->m
.file_mode
& S_IRWXUGO
) | S_IFREG
;
587 server
->m
.dir_mode
= (server
->m
.dir_mode
& S_IRWXUGO
) | S_IFDIR
;
589 #ifdef CONFIG_NCPFS_NLS
590 /* load the default NLS charsets */
591 server
->nls_vol
= load_nls_default();
592 server
->nls_io
= load_nls_default();
593 #endif /* CONFIG_NCPFS_NLS */
595 server
->dentry_ttl
= 0; /* no caching */
597 INIT_LIST_HEAD(&server
->tx
.requests
);
598 mutex_init(&server
->rcv
.creq_mutex
);
599 server
->tx
.creq
= NULL
;
600 server
->rcv
.creq
= NULL
;
601 server
->data_ready
= sock
->sk
->sk_data_ready
;
602 server
->write_space
= sock
->sk
->sk_write_space
;
603 server
->error_report
= sock
->sk
->sk_error_report
;
604 sock
->sk
->sk_user_data
= server
;
606 init_timer(&server
->timeout_tm
);
607 #undef NCP_PACKET_SIZE
608 #define NCP_PACKET_SIZE 131072
610 server
->packet_size
= NCP_PACKET_SIZE
;
611 server
->packet
= vmalloc(NCP_PACKET_SIZE
);
612 if (server
->packet
== NULL
)
614 server
->txbuf
= vmalloc(NCP_PACKET_SIZE
);
615 if (server
->txbuf
== NULL
)
617 server
->rxbuf
= vmalloc(NCP_PACKET_SIZE
);
618 if (server
->rxbuf
== NULL
)
621 sock
->sk
->sk_data_ready
= ncp_tcp_data_ready
;
622 sock
->sk
->sk_error_report
= ncp_tcp_error_report
;
623 if (sock
->type
== SOCK_STREAM
) {
624 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
;
625 server
->rcv
.len
= 10;
626 server
->rcv
.state
= 0;
627 INIT_WORK(&server
->rcv
.tq
, ncp_tcp_rcv_proc
);
628 INIT_WORK(&server
->tx
.tq
, ncp_tcp_tx_proc
);
629 sock
->sk
->sk_write_space
= ncp_tcp_write_space
;
631 INIT_WORK(&server
->rcv
.tq
, ncpdgram_rcv_proc
);
632 INIT_WORK(&server
->timeout_tq
, ncpdgram_timeout_proc
);
633 server
->timeout_tm
.data
= (unsigned long)server
;
634 server
->timeout_tm
.function
= ncpdgram_timeout_call
;
637 ncp_lock_server(server
);
638 error
= ncp_connect(server
);
639 ncp_unlock_server(server
);
642 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb
));
644 error
= -EMSGSIZE
; /* -EREMOTESIDEINCOMPATIBLE */
645 #ifdef CONFIG_NCPFS_PACKET_SIGNING
646 if (ncp_negotiate_size_and_options(server
, default_bufsize
,
647 NCP_DEFAULT_OPTIONS
, &(server
->buffer_size
), &options
) == 0)
649 if (options
!= NCP_DEFAULT_OPTIONS
)
651 if (ncp_negotiate_size_and_options(server
,
654 &(server
->buffer_size
), &options
) != 0)
661 server
->sign_wanted
= 1;
664 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
665 if (ncp_negotiate_buffersize(server
, default_bufsize
,
666 &(server
->buffer_size
)) != 0)
668 DPRINTK("ncpfs: bufsize = %d\n", server
->buffer_size
);
670 memset(&finfo
, 0, sizeof(finfo
));
671 finfo
.i
.attributes
= aDIR
;
672 finfo
.i
.dataStreamSize
= 0; /* ignored */
673 finfo
.i
.dirEntNum
= 0;
674 finfo
.i
.DosDirNum
= 0;
675 #ifdef CONFIG_NCPFS_SMALLDOS
676 finfo
.i
.NSCreator
= NW_NS_DOS
;
678 finfo
.volume
= NCP_NUMBER_OF_VOLUMES
;
679 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
680 finfo
.i
.creationTime
= finfo
.i
.modifyTime
681 = cpu_to_le16(0x0000);
682 finfo
.i
.creationDate
= finfo
.i
.modifyDate
683 = finfo
.i
.lastAccessDate
684 = cpu_to_le16(0x0C21);
686 finfo
.i
.entryName
[0] = '\0';
689 finfo
.ino
= 2; /* tradition */
691 server
->name_space
[finfo
.volume
] = NW_NS_DOS
;
694 root_inode
= ncp_iget(sb
, &finfo
);
697 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode
)->volNumber
);
698 sb
->s_root
= d_alloc_root(root_inode
);
701 sb
->s_root
->d_op
= &ncp_root_dentry_operations
;
707 ncp_lock_server(server
);
708 ncp_disconnect(server
);
709 ncp_unlock_server(server
);
711 ncp_stop_tasks(server
);
712 vfree(server
->rxbuf
);
714 vfree(server
->txbuf
);
716 vfree(server
->packet
);
718 #ifdef CONFIG_NCPFS_NLS
719 unload_nls(server
->nls_io
);
720 unload_nls(server
->nls_vol
);
723 if (server
->info_filp
)
724 fput(server
->info_filp
);
726 bdi_destroy(&server
->bdi
);
728 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
730 * The previously used put_filp(ncp_filp); was bogus, since
731 * it doesn't perform proper unlocking.
735 put_pid(data
.wdog_pid
);
736 sb
->s_fs_info
= NULL
;
741 static void ncp_put_super(struct super_block
*sb
)
743 struct ncp_server
*server
= NCP_SBP(sb
);
747 ncp_lock_server(server
);
748 ncp_disconnect(server
);
749 ncp_unlock_server(server
);
751 ncp_stop_tasks(server
);
753 #ifdef CONFIG_NCPFS_NLS
754 /* unload the NLS charsets */
755 unload_nls(server
->nls_vol
);
756 unload_nls(server
->nls_io
);
757 #endif /* CONFIG_NCPFS_NLS */
759 if (server
->info_filp
)
760 fput(server
->info_filp
);
761 fput(server
->ncp_filp
);
762 kill_pid(server
->m
.wdog_pid
, SIGTERM
, 1);
763 put_pid(server
->m
.wdog_pid
);
765 bdi_destroy(&server
->bdi
);
766 kfree(server
->priv
.data
);
767 kfree(server
->auth
.object_name
);
768 vfree(server
->rxbuf
);
769 vfree(server
->txbuf
);
770 vfree(server
->packet
);
771 sb
->s_fs_info
= NULL
;
777 static int ncp_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
781 struct ncp_inode_info
* ni
;
782 struct ncp_server
* s
;
783 struct ncp_volume_info vi
;
784 struct super_block
*sb
= dentry
->d_sb
;
804 if (!s
->m
.mounted_vol
[0]) {
808 err
= ncp_dirhandle_alloc(s
, ni
->volNumber
, ni
->DosDirNum
, &dh
);
812 err
= ncp_get_directory_info(s
, dh
, &vi
);
813 ncp_dirhandle_free(s
, dh
);
817 buf
->f_type
= NCP_SUPER_MAGIC
;
818 buf
->f_bsize
= vi
.sectors_per_block
* 512;
819 buf
->f_blocks
= vi
.total_blocks
;
820 buf
->f_bfree
= vi
.free_blocks
;
821 buf
->f_bavail
= vi
.free_blocks
;
822 buf
->f_files
= vi
.total_dir_entries
;
823 buf
->f_ffree
= vi
.available_dir_entries
;
827 /* We cannot say how much disk space is left on a mounted
828 NetWare Server, because free space is distributed over
829 volumes, and the current user might have disk quotas. So
830 free space is not that simple to determine. Our decision
831 here is to err conservatively. */
834 buf
->f_type
= NCP_SUPER_MAGIC
;
835 buf
->f_bsize
= NCP_BLOCK_SIZE
;
843 int ncp_notify_change(struct dentry
*dentry
, struct iattr
*attr
)
845 struct inode
*inode
= dentry
->d_inode
;
848 struct nw_modify_dos_info info
;
849 struct ncp_server
*server
;
855 server
= NCP_SERVER(inode
);
856 if ((!server
) || !ncp_conn_valid(server
))
859 /* ageing the dentry to force validation */
860 ncp_age_dentry(server
, dentry
);
862 result
= inode_change_ok(inode
, attr
);
867 if (((attr
->ia_valid
& ATTR_UID
) &&
868 (attr
->ia_uid
!= server
->m
.uid
)))
871 if (((attr
->ia_valid
& ATTR_GID
) &&
872 (attr
->ia_gid
!= server
->m
.gid
)))
875 if (((attr
->ia_valid
& ATTR_MODE
) &&
877 ~(S_IFREG
| S_IFDIR
| S_IRWXUGO
))))
881 memset(&info
, 0, sizeof(info
));
883 if ((attr
->ia_valid
& ATTR_MODE
) != 0)
885 umode_t newmode
= attr
->ia_mode
;
887 info_mask
|= DM_ATTRIBUTES
;
889 if (S_ISDIR(inode
->i_mode
)) {
890 newmode
&= server
->m
.dir_mode
;
892 #ifdef CONFIG_NCPFS_EXTRAS
893 if (server
->m
.flags
& NCP_MOUNT_EXTRAS
) {
894 /* any non-default execute bit set */
895 if (newmode
& ~server
->m
.file_mode
& S_IXUGO
)
896 info
.attributes
|= aSHARED
| aSYSTEM
;
897 /* read for group/world and not in default file_mode */
898 else if (newmode
& ~server
->m
.file_mode
& S_IRUGO
)
899 info
.attributes
|= aSHARED
;
902 newmode
&= server
->m
.file_mode
;
904 if (newmode
& S_IWUGO
)
905 info
.attributes
&= ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
907 info
.attributes
|= (aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
909 #ifdef CONFIG_NCPFS_NFS_NS
910 if (ncp_is_nfs_extras(server
, NCP_FINFO(inode
)->volNumber
)) {
911 result
= ncp_modify_nfs_info(server
,
912 NCP_FINFO(inode
)->volNumber
,
913 NCP_FINFO(inode
)->dirEntNum
,
917 info
.attributes
&= ~(aSHARED
| aSYSTEM
);
919 /* mark partial success */
920 struct iattr tmpattr
;
922 tmpattr
.ia_valid
= ATTR_MODE
;
923 tmpattr
.ia_mode
= attr
->ia_mode
;
925 setattr_copy(inode
, &tmpattr
);
926 mark_inode_dirty(inode
);
932 /* Do SIZE before attributes, otherwise mtime together with size does not work...
934 if ((attr
->ia_valid
& ATTR_SIZE
) != 0) {
937 DPRINTK("ncpfs: trying to change size to %ld\n",
940 if ((result
= ncp_make_open(inode
, O_WRONLY
)) < 0) {
944 ncp_write_kernel(NCP_SERVER(inode
), NCP_FINFO(inode
)->file_handle
,
945 attr
->ia_size
, 0, "", &written
);
947 /* According to ndir, the changes only take effect after
949 ncp_inode_close(inode
);
950 result
= ncp_make_closed(inode
);
954 if (attr
->ia_size
!= i_size_read(inode
)) {
955 result
= vmtruncate(inode
, attr
->ia_size
);
958 mark_inode_dirty(inode
);
961 if ((attr
->ia_valid
& ATTR_CTIME
) != 0) {
962 info_mask
|= (DM_CREATE_TIME
| DM_CREATE_DATE
);
963 ncp_date_unix2dos(attr
->ia_ctime
.tv_sec
,
964 &info
.creationTime
, &info
.creationDate
);
966 if ((attr
->ia_valid
& ATTR_MTIME
) != 0) {
967 info_mask
|= (DM_MODIFY_TIME
| DM_MODIFY_DATE
);
968 ncp_date_unix2dos(attr
->ia_mtime
.tv_sec
,
969 &info
.modifyTime
, &info
.modifyDate
);
971 if ((attr
->ia_valid
& ATTR_ATIME
) != 0) {
973 info_mask
|= (DM_LAST_ACCESS_DATE
);
974 ncp_date_unix2dos(attr
->ia_atime
.tv_sec
,
975 &dummy
, &info
.lastAccessDate
);
977 if (info_mask
!= 0) {
978 result
= ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode
),
979 inode
, info_mask
, &info
);
983 if (info_mask
== (DM_CREATE_TIME
| DM_CREATE_DATE
)) {
984 /* NetWare seems not to allow this. I
985 do not know why. So, just tell the
986 user everything went fine. This is
987 a terrible hack, but I do not know
988 how to do this correctly. */
993 #ifdef CONFIG_NCPFS_STRONG
994 if ((!result
) && (info_mask
& DM_ATTRIBUTES
))
995 NCP_FINFO(inode
)->nwattr
= info
.attributes
;
1001 setattr_copy(inode
, attr
);
1002 mark_inode_dirty(inode
);
1009 static int ncp_get_sb(struct file_system_type
*fs_type
,
1010 int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
1012 return get_sb_nodev(fs_type
, flags
, data
, ncp_fill_super
, mnt
);
1015 static struct file_system_type ncp_fs_type
= {
1016 .owner
= THIS_MODULE
,
1018 .get_sb
= ncp_get_sb
,
1019 .kill_sb
= kill_anon_super
,
1020 .fs_flags
= FS_BINARY_MOUNTDATA
,
1023 static int __init
init_ncp_fs(void)
1026 DPRINTK("ncpfs: init_ncp_fs called\n");
1028 err
= init_inodecache();
1031 err
= register_filesystem(&ncp_fs_type
);
1036 destroy_inodecache();
1041 static void __exit
exit_ncp_fs(void)
1043 DPRINTK("ncpfs: exit_ncp_fs called\n");
1044 unregister_filesystem(&ncp_fs_type
);
1045 destroy_inodecache();
1048 module_init(init_ncp_fs
)
1049 module_exit(exit_ncp_fs
)
1050 MODULE_LICENSE("GPL");