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 = 1024;
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 char command[ sizeof(server->m.mount_point)
374 + sizeof(NCP_MSG_COMMAND) + 2];
375
376 if (server == NULL)
377 {
378 printk("ncp_trigger_message: invalid server!\n");
379 return;
380 }
381
382 DPRINTK("ncp_trigger_message: on %s\n",
383 server->m.mount_point);
384
385 #ifdef CONFIG_KERNELD
386 strcpy(command, NCP_MSG_COMMAND);
387 strcat(command, " ");
388 strcat(command, server->m.mount_point);
389 DPRINTK("ksystem: %s\n", command);
390 ksystem(command, KERNELD_NOWAIT);
391 #endif
392 }
393
394 static void
395 ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
396 {
397 struct statfs tmp;
398
399
400
401
402
403
404
405 tmp.f_type = NCP_SUPER_MAGIC;
406 tmp.f_bsize = 512;
407 tmp.f_blocks = 0;
408 tmp.f_bfree = 0;
409 tmp.f_bavail = 0;
410 tmp.f_files = -1;
411 tmp.f_ffree = -1;
412 tmp.f_namelen = 12;
413 memcpy_tofs(buf, &tmp, bufsiz);
414 }
415
416 static int
417 ncp_notify_change(struct inode *inode, struct iattr *attr)
418 {
419 int result = 0;
420 int info_mask;
421 struct nw_modify_dos_info info;
422
423 if (!ncp_conn_valid(NCP_SERVER(inode)))
424 {
425 return -EIO;
426 }
427
428 if ((result = inode_change_ok(inode, attr)) < 0)
429 return result;
430
431 if (((attr->ia_valid & ATTR_UID) &&
432 (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
433 return -EPERM;
434
435 if (((attr->ia_valid & ATTR_GID) &&
436 (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
437 return -EPERM;
438
439 if (((attr->ia_valid & ATTR_MODE) &&
440 (attr->ia_mode &
441 ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
442 return -EPERM;
443
444 info_mask = 0;
445 memset(&info, 0, sizeof(info));
446
447 if ((attr->ia_valid & ATTR_CTIME) != 0)
448 {
449 info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
450 ncp_date_unix2dos(attr->ia_ctime,
451 &(info.creationTime), &(info.creationDate));
452 }
453
454 if ((attr->ia_valid & ATTR_MTIME) != 0)
455 {
456 info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
457 ncp_date_unix2dos(attr->ia_mtime,
458 &(info.modifyTime), &(info.modifyDate));
459 }
460
461 if ((attr->ia_valid & ATTR_ATIME) != 0)
462 {
463 __u16 dummy;
464 info_mask |= (DM_LAST_ACCESS_DATE);
465 ncp_date_unix2dos(attr->ia_ctime,
466 &(dummy), &(info.lastAccessDate));
467 }
468
469 if (info_mask != 0)
470 {
471 if ((result =
472 ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
473 NCP_ISTRUCT(inode),
474 info_mask,
475 &info)) != 0)
476 {
477 result = -EACCES;
478
479 if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
480 {
481
482
483
484
485
486 result = 0;
487 }
488 }
489 }
490
491 if ((attr->ia_valid & ATTR_SIZE) != 0)
492 {
493 int written;
494
495 DPRINTK("ncpfs: trying to change size of %s to %ld\n",
496 NCP_ISTRUCT(inode)->entryName, attr->ia_size);
497
498 if ((result = ncp_make_open(inode, O_RDWR)) < 0)
499 {
500 return -EACCES;
501 }
502
503 ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
504 attr->ia_size, 0, "", &written);
505
506
507
508 ncp_close_file(NCP_SERVER(inode),
509 NCP_FINFO(inode)->file_handle);
510 NCP_FINFO(inode)->opened = 0;
511
512 result = 0;
513 }
514
515 ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
516
517 return result;
518 }
519
520 #ifdef DEBUG_NCP_MALLOC
521 int ncp_malloced;
522 int ncp_current_malloced;
523 #endif
524
525 static struct file_system_type ncp_fs_type = {
526 ncp_read_super, "ncpfs", 0, NULL
527 };
528
529 int init_ncp_fs(void)
530 {
531 return register_filesystem(&ncp_fs_type);
532 }
533
534 #ifdef MODULE
535 int
536 init_module( void)
537 {
538 int status;
539
540 DPRINTK("ncpfs: init_module called\n");
541
542 #ifdef DEBUG_NCP_MALLOC
543 ncp_malloced = 0;
544 ncp_current_malloced = 0;
545 #endif
546 ncp_init_dir_cache();
547
548 if ((status = init_ncp_fs()) == 0)
549 register_symtab(0);
550 return status;
551 }
552
553 void
554 cleanup_module(void)
555 {
556 DPRINTK("ncpfs: cleanup_module called\n");
557 ncp_free_dir_cache();
558 unregister_filesystem(&ncp_fs_type);
559 #ifdef DEBUG_NCP_MALLOC
560 printk("ncp_malloced: %d\n", ncp_malloced);
561 printk("ncp_current_malloced: %d\n", ncp_current_malloced);
562 #endif
563 }
564
565 #endif