This source file includes following definitions.
- ncp_read_inode
- ncp_put_inode
- ncp_read_super
- ncp_put_super
- ncp_trigger_message
- ncp_statfs
- ncp_notify_change
- init_ncp_fs
- init_module
- cleanup_module
1
2
3
4
5
6
7
8 #include <linux/module.h>
9 #include <linux/config.h>
10
11 #include <asm/system.h>
12 #include <asm/segment.h>
13
14 #include <linux/sched.h>
15 #include <linux/ncp_fs.h>
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/string.h>
19 #include <linux/stat.h>
20 #include <linux/errno.h>
21 #include <linux/locks.h>
22 #include <linux/fcntl.h>
23 #include <linux/malloc.h>
24 #ifdef CONFIG_KERNELD
25 #include <linux/kerneld.h>
26 #endif
27 #include "ncplib_kernel.h"
28
29 extern int close_fp(struct file *filp);
30
31 static void ncp_put_inode(struct inode *);
32 static void ncp_read_inode(struct inode *);
33 static void ncp_put_super(struct super_block *);
34 static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
35 static int ncp_notify_change(struct inode *inode, struct iattr *attr);
36
37 static struct super_operations ncp_sops = {
38 ncp_read_inode,
39 ncp_notify_change,
40 NULL,
41 ncp_put_inode,
42 ncp_put_super,
43 NULL,
44 ncp_statfs,
45 NULL
46 };
47
48
49
50
51
52 static void
53 ncp_read_inode(struct inode *inode)
54 {
55
56
57
58
59
60
61 struct ncp_inode_info *inode_info = ncp_find_inode(inode);
62
63 if (inode_info == NULL)
64 {
65
66
67 printk("ncp_read_inode: inode info not found\n");
68 return;
69 }
70
71 inode_info->state = NCP_INODE_VALID;
72
73 NCP_INOP(inode) = inode_info;
74 inode_info->inode = inode;
75
76 if (NCP_ISTRUCT(inode)->attributes & aDIR)
77 {
78 inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
79
80
81 inode->i_size = 512;
82 }
83 else
84 {
85 inode->i_mode = NCP_SERVER(inode)->m.file_mode;
86 inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
87 }
88
89 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
90
91 inode->i_nlink = 1;
92 inode->i_uid = NCP_SERVER(inode)->m.uid;
93 inode->i_gid = NCP_SERVER(inode)->m.gid;
94 inode->i_blksize = 512;
95 inode->i_rdev = 0;
96
97 if ((inode->i_blksize != 0) && (inode->i_size != 0))
98 {
99 inode->i_blocks =
100 (inode->i_size - 1) / inode->i_blksize + 1;
101 }
102 else
103 {
104 inode->i_blocks = 0;
105 }
106
107 inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
108 NCP_ISTRUCT(inode)->modifyDate);
109 inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
110 NCP_ISTRUCT(inode)->creationDate);
111 inode->i_atime = ncp_date_dos2unix(0,
112 NCP_ISTRUCT(inode)->lastAccessDate);
113
114 if (S_ISREG(inode->i_mode))
115 {
116 inode->i_op = &ncp_file_inode_operations;
117 }
118 else if (S_ISDIR(inode->i_mode))
119 {
120 inode->i_op = &ncp_dir_inode_operations;
121 }
122 else
123 {
124 inode->i_op = NULL;
125 }
126 }
127
128 static void
129 ncp_put_inode(struct inode *inode)
130 {
131 struct nw_file_info *finfo = NCP_FINFO(inode);
132
133 if (finfo->opened != 0)
134 {
135 if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
136 {
137
138 printk("ncp_put_inode: could not close\n");
139 }
140 }
141
142 DDPRINTK("ncp_put_inode: put %s\n",
143 finfo->i.entryName);
144
145 ncp_free_inode_info(NCP_INOP(inode));
146
147 if (S_ISDIR(inode->i_mode))
148 {
149 DDPRINTK("ncp_put_inode: put directory %ld\n",
150 inode->i_ino);
151 ncp_invalid_dir_cache(inode);
152 }
153
154 clear_inode(inode);
155 }
156
157 struct super_block *
158 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
159 {
160 struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
161 struct ncp_server *server;
162 struct file *ncp_filp;
163 struct file *wdog_filp;
164 struct file *msg_filp;
165 kdev_t dev = sb->s_dev;
166 int error;
167
168 if (data == NULL)
169 {
170 printk("ncp_read_super: missing data argument\n");
171 sb->s_dev = 0;
172 return NULL;
173 }
174
175 if (data->version != NCP_MOUNT_VERSION)
176 {
177 printk("ncp warning: mount version %s than kernel\n",
178 (data->version < NCP_MOUNT_VERSION) ?
179 "older" : "newer");
180 sb->s_dev = 0;
181 return NULL;
182 }
183
184 if ( (data->ncp_fd >= NR_OPEN)
185 || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
186 || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
187 {
188 printk("ncp_read_super: invalid ncp socket\n");
189 sb->s_dev = 0;
190 return NULL;
191 }
192
193 if ( (data->wdog_fd >= NR_OPEN)
194 || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
195 || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
196 {
197 printk("ncp_read_super: invalid wdog socket\n");
198 sb->s_dev = 0;
199 return NULL;
200 }
201
202 if ( (data->message_fd >= NR_OPEN)
203 || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
204 || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
205 {
206 printk("ncp_read_super: invalid wdog socket\n");
207 sb->s_dev = 0;
208 return NULL;
209 }
210
211
212 server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
213 GFP_KERNEL);
214
215 if (server == NULL)
216 {
217 printk("ncp_read_super: could not alloc ncp_server\n");
218 return NULL;
219 }
220
221 ncp_filp->f_count += 1;
222 wdog_filp->f_count += 1;
223 msg_filp->f_count += 1;
224
225 lock_super(sb);
226
227 NCP_SBP(sb) = server;
228
229 sb->s_blocksize = 1024;
230 sb->s_blocksize_bits = 10;
231 sb->s_magic = NCP_SUPER_MAGIC;
232 sb->s_dev = dev;
233 sb->s_op = &ncp_sops;
234
235 server->ncp_filp = ncp_filp;
236 server->wdog_filp = wdog_filp;
237 server->msg_filp = msg_filp;
238 server->lock = 0;
239 server->wait = NULL;
240 server->packet = NULL;
241 server->buffer_size = 0;
242 server->conn_status = 0;
243
244 server->m = *data;
245 server->m.file_mode = (server->m.file_mode &
246 (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
247 server->m.dir_mode = (server->m.dir_mode &
248 (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
249
250
251 server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';
252
253 server->packet_size = NCP_PACKET_SIZE;
254 server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
255
256 if (server->packet == NULL)
257 {
258 printk("ncpfs: could not alloc packet\n");
259 error = -ENOMEM;
260 unlock_super(sb);
261 goto fail;
262 }
263
264
265
266
267
268 if (ncp_catch_watchdog(server) != 0)
269 {
270 printk("ncp_read_super: Could not catch watchdog\n");
271 error = -EINVAL;
272 unlock_super(sb);
273 goto fail;
274 }
275
276 if (ncp_catch_message(server) != 0)
277 {
278 printk("ncp_read_super: Could not catch messages\n");
279 ncp_dont_catch_watchdog(server);
280 error = -EINVAL;
281 unlock_super(sb);
282 goto fail;
283 }
284
285 ncp_lock_server(server);
286 error = ncp_connect(server);
287 ncp_unlock_server(server);
288 unlock_super(sb);
289
290 if (error < 0)
291 {
292 sb->s_dev = 0;
293 printk("ncp_read_super: Failed connection, bailing out "
294 "(error = %d).\n", -error);
295 ncp_kfree_s(server->packet, server->packet_size);
296 ncp_dont_catch_watchdog(server);
297 goto fail;
298 }
299
300 DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
301
302 ncp_init_root(server);
303
304 if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
305 {
306 sb->s_dev = 0;
307 printk("ncp_read_super: get root inode failed\n");
308 goto disconnect;
309 }
310
311 if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
312 &(server->buffer_size)) != 0)
313 {
314 sb->s_dev = 0;
315 printk("ncp_read_super: could not get bufsize\n");
316 goto disconnect;
317 }
318
319 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
320
321 MOD_INC_USE_COUNT;
322 return sb;
323
324 disconnect:
325 ncp_lock_server(server);
326 ncp_disconnect(server);
327 ncp_unlock_server(server);
328 ncp_kfree_s(server->packet, server->packet_size);
329 ncp_dont_catch_watchdog(server);
330 fail:
331 ncp_filp->f_count -= 1;
332 wdog_filp->f_count -= 1;
333 msg_filp->f_count -= 1;
334 ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
335 return NULL;
336 }
337
338 static void
339 ncp_put_super(struct super_block *sb)
340 {
341 struct ncp_server *server = NCP_SBP(sb);
342
343 lock_super(sb);
344
345 ncp_lock_server(server);
346 ncp_disconnect(server);
347 ncp_unlock_server(server);
348
349 close_fp(server->ncp_filp);
350
351 ncp_dont_catch_watchdog(server);
352 close_fp(server->wdog_filp);
353 close_fp(server->msg_filp);
354
355 ncp_free_all_inodes(server);
356
357 ncp_kfree_s(server->packet, server->packet_size);
358
359 sb->s_dev = 0;
360 ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
361 NCP_SBP(sb) = NULL;
362
363 unlock_super(sb);
364
365 MOD_DEC_USE_COUNT;
366 }
367
368
369
370 void
371 ncp_trigger_message(struct ncp_server *server)
372 {
373 #ifdef CONFIG_KERNELD
374 char command[ sizeof(server->m.mount_point)
375 + sizeof(NCP_MSG_COMMAND) + 2];
376 #endif
377
378 if (server == NULL)
379 {
380 printk("ncp_trigger_message: invalid server!\n");
381 return;
382 }
383
384 DPRINTK("ncp_trigger_message: on %s\n",
385 server->m.mount_point);
386
387 #ifdef CONFIG_KERNELD
388 strcpy(command, NCP_MSG_COMMAND);
389 strcat(command, " ");
390 strcat(command, server->m.mount_point);
391 DPRINTK("ksystem: %s\n", command);
392 ksystem(command, KERNELD_NOWAIT);
393 #endif
394 }
395
396 static void
397 ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
398 {
399 struct statfs tmp;
400
401
402
403
404
405
406
407 tmp.f_type = NCP_SUPER_MAGIC;
408 tmp.f_bsize = 512;
409 tmp.f_blocks = 0;
410 tmp.f_bfree = 0;
411 tmp.f_bavail = 0;
412 tmp.f_files = -1;
413 tmp.f_ffree = -1;
414 tmp.f_namelen = 12;
415 memcpy_tofs(buf, &tmp, bufsiz);
416 }
417
418 static int
419 ncp_notify_change(struct inode *inode, struct iattr *attr)
420 {
421 int result = 0;
422 int info_mask;
423 struct nw_modify_dos_info info;
424
425 if (!ncp_conn_valid(NCP_SERVER(inode)))
426 {
427 return -EIO;
428 }
429
430 if ((result = inode_change_ok(inode, attr)) < 0)
431 return result;
432
433 if (((attr->ia_valid & ATTR_UID) &&
434 (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
435 return -EPERM;
436
437 if (((attr->ia_valid & ATTR_GID) &&
438 (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
439 return -EPERM;
440
441 if (((attr->ia_valid & ATTR_MODE) &&
442 (attr->ia_mode &
443 ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
444 return -EPERM;
445
446 info_mask = 0;
447 memset(&info, 0, sizeof(info));
448
449 if ((attr->ia_valid & ATTR_CTIME) != 0)
450 {
451 info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
452 ncp_date_unix2dos(attr->ia_ctime,
453 &(info.creationTime), &(info.creationDate));
454 }
455
456 if ((attr->ia_valid & ATTR_MTIME) != 0)
457 {
458 info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
459 ncp_date_unix2dos(attr->ia_mtime,
460 &(info.modifyTime), &(info.modifyDate));
461 }
462
463 if ((attr->ia_valid & ATTR_ATIME) != 0)
464 {
465 __u16 dummy;
466 info_mask |= (DM_LAST_ACCESS_DATE);
467 ncp_date_unix2dos(attr->ia_ctime,
468 &(dummy), &(info.lastAccessDate));
469 }
470
471 if (info_mask != 0)
472 {
473 if ((result =
474 ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
475 NCP_ISTRUCT(inode),
476 info_mask,
477 &info)) != 0)
478 {
479 result = -EACCES;
480
481 if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
482 {
483
484
485
486
487
488 result = 0;
489 }
490 }
491 }
492
493 if ((attr->ia_valid & ATTR_SIZE) != 0)
494 {
495 int written;
496
497 DPRINTK("ncpfs: trying to change size of %s to %ld\n",
498 NCP_ISTRUCT(inode)->entryName, attr->ia_size);
499
500 if ((result = ncp_make_open(inode, O_RDWR)) < 0)
501 {
502 return -EACCES;
503 }
504
505 ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
506 attr->ia_size, 0, "", &written);
507
508
509
510 ncp_close_file(NCP_SERVER(inode),
511 NCP_FINFO(inode)->file_handle);
512 NCP_FINFO(inode)->opened = 0;
513
514 result = 0;
515 }
516
517 ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
518
519 return result;
520 }
521
522 #ifdef DEBUG_NCP_MALLOC
523 int ncp_malloced;
524 int ncp_current_malloced;
525 #endif
526
527 static struct file_system_type ncp_fs_type = {
528 ncp_read_super, "ncpfs", 0, NULL
529 };
530
531 int init_ncp_fs(void)
532 {
533 return register_filesystem(&ncp_fs_type);
534 }
535
536 #ifdef MODULE
537 int
538 init_module( void)
539 {
540 int status;
541
542 DPRINTK("ncpfs: init_module called\n");
543
544 #ifdef DEBUG_NCP_MALLOC
545 ncp_malloced = 0;
546 ncp_current_malloced = 0;
547 #endif
548 ncp_init_dir_cache();
549
550 if ((status = init_ncp_fs()) == 0)
551 register_symtab(0);
552 return status;
553 }
554
555 void
556 cleanup_module(void)
557 {
558 DPRINTK("ncpfs: cleanup_module called\n");
559 ncp_free_dir_cache();
560 unregister_filesystem(&ncp_fs_type);
561 #ifdef DEBUG_NCP_MALLOC
562 printk("ncp_malloced: %d\n", ncp_malloced);
563 printk("ncp_current_malloced: %d\n", ncp_current_malloced);
564 #endif
565 }
566
567 #endif