OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ncpfs/] [inode.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  inode.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Volker Lendecke
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
 
36
static struct super_operations ncp_sops = {
37
        ncp_read_inode,         /* read inode */
38
        ncp_notify_change,      /* notify change */
39
        NULL,                   /* write inode */
40
        ncp_put_inode,          /* put inode */
41
        ncp_put_super,          /* put superblock */
42
        NULL,                   /* write superblock */
43
        ncp_statfs,             /* stat filesystem */
44
        NULL
45
};
46
 
47
/* ncp_read_inode: Called from iget, it only traverses the allocated
48
   ncp_inode_info's and initializes the inode from the data found
49
   there.  It does not allocate or deallocate anything. */
50
 
51
static void
52
ncp_read_inode(struct inode *inode)
53
{
54
        /* Our task should be extremely simple here. We only have to
55
           look up the information somebody else (ncp_iget) put into
56
           the inode tree. The address of this information is the
57
           inode->i_ino. Just to make sure everything went well, we
58
           check it's there. */
59
 
60
        struct ncp_inode_info *inode_info = ncp_find_inode(inode);
61
 
62
        if (inode_info == NULL)
63
        {
64
                /* Ok, now we're in trouble. The inode info is not there. What
65
                   should we do now??? */
66
                printk("ncp_read_inode: inode info not found\n");
67
                return;
68
        }
69
 
70
        inode_info->state = NCP_INODE_VALID;
71
 
72
        NCP_INOP(inode) = inode_info;
73
        inode_info->inode = inode;
74
 
75
        if (NCP_ISTRUCT(inode)->attributes & aDIR)
76
        {
77
                inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
78
                /* for directories dataStreamSize seems to be some
79
                   Object ID ??? */
80
                inode->i_size = 512;
81
        }
82
        else
83
        {
84
                inode->i_mode = NCP_SERVER(inode)->m.file_mode;
85
#if 1
86
                if (NCP_ISTRUCT(inode)->attributes & /* 0x60001 incl. DiRi */ 1) inode->i_mode &= ~0222;
87
#endif
88
                inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
89
        }
90
 
91
        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
92
 
93
        inode->i_nlink   = 1;
94
        inode->i_uid     = NCP_SERVER(inode)->m.uid;
95
        inode->i_gid     = NCP_SERVER(inode)->m.gid;
96
        inode->i_blksize = 512;
97
        inode->i_rdev    = 0;
98
 
99
        if ((inode->i_blksize != 0) && (inode->i_size != 0))
100
        {
101
                inode->i_blocks =
102
                        (inode->i_size - 1) / inode->i_blksize + 1;
103
        }
104
        else
105
        {
106
                inode->i_blocks = 0;
107
        }
108
 
109
        inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
110
                                           NCP_ISTRUCT(inode)->modifyDate);
111
        inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
112
                                           NCP_ISTRUCT(inode)->creationDate);
113
        inode->i_atime = ncp_date_dos2unix(0,
114
                                           NCP_ISTRUCT(inode)->lastAccessDate);
115
 
116
        if (S_ISREG(inode->i_mode))
117
        {
118
                inode->i_op = &ncp_file_inode_operations;
119
        }
120
        else if (S_ISDIR(inode->i_mode))
121
        {
122
                inode->i_op = &ncp_dir_inode_operations;
123
        }
124
        else
125
        {
126
                inode->i_op = NULL;
127
        }
128
}
129
 
130
/*
131
 * Defer release of inode_info and file_info structures until the inode
132
 * has been cleared.  This avoids a race condition allowing the inode to
133
 * be put back in use before being cleared. Also, temporarily increment
134
 * i_count after clear_inode() so that the inode can't be reused.
135
 */
136
static void
137
ncp_put_inode(struct inode *inode)
138
{
139
        struct super_block      *sb     = inode->i_sb;
140
        struct ncp_server       *server = NCP_SERVER(inode);
141
        struct ncp_inode_info   *iinfo  = NCP_INOP(inode);
142
        struct nw_file_info     *finfo  = NCP_FINFO(inode);
143
 
144
        /*
145
         * This operation may block, so we lock before checking the count.
146
         */
147
        lock_super(sb);
148
 
149
        if (inode->i_count > 1)
150
        {
151
                printk("ncp_put_inode: inode in use device %s, inode %ld, count=%ld\n",
152
                       kdevname(inode->i_dev), inode->i_ino, inode->i_count);
153
                goto unlock;
154
        }
155
 
156
        DDPRINTK("ncp_put_inode: put %s\n",
157
                 finfo->i.entryName);
158
        /*
159
         * This operation should never block.
160
         */
161
        if (S_ISDIR(inode->i_mode))
162
        {
163
                DDPRINTK("ncp_put_inode: put directory %ld\n",
164
                         inode->i_ino);
165
                ncp_invalid_dir_cache(inode);
166
        }
167
 
168
        clear_inode(inode);
169
 
170
        /*
171
         * After clearing the inode i_count will be 0 in 2.0.xx kernels.
172
         * To keep the inode from being reused as free if we block while
173
         * closing the file, increment i_count temporarily.
174
         */
175
        inode->i_count++;
176
 
177
        if (finfo->opened != 0)
178
        {
179
                if (ncp_close_file(server, finfo->file_handle) != 0)
180
                {
181
                        /* We can't do anything but complain. */
182
                        printk("ncp_put_inode: could not close %s\n",
183
                                finfo->i.entryName);
184
                }
185
        }
186
 
187
        ncp_free_inode_info(iinfo);
188
        inode->i_count--;
189
 
190
unlock:
191
        unlock_super(sb);
192
}
193
 
194
struct super_block *
195
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
196
{
197
        struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
198
        struct ncp_server *server;
199
        struct file *ncp_filp;
200
        struct file *wdog_filp;
201
        struct file *msg_filp;
202
        kdev_t dev = sb->s_dev;
203
        int error;
204
#ifdef CONFIG_NCPFS_PACKET_SIGNING
205
        int options;
206
#endif
207
 
208
        if (data == NULL)
209
        {
210
                printk("ncp_read_super: missing data argument\n");
211
                sb->s_dev = 0;
212
                return NULL;
213
        }
214
 
215
        if (data->version != NCP_MOUNT_VERSION)
216
        {
217
                printk("ncp warning: mount version %s than kernel\n",
218
                       (data->version < NCP_MOUNT_VERSION) ?
219
                       "older" : "newer");
220
                sb->s_dev = 0;
221
                return NULL;
222
        }
223
 
224
        if (   (data->ncp_fd >= NR_OPEN)
225
            || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
226
            || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
227
        {
228
                printk("ncp_read_super: invalid ncp socket\n");
229
                sb->s_dev = 0;
230
                return NULL;
231
        }
232
 
233
        if (   (data->wdog_fd >= NR_OPEN)
234
            || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
235
            || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
236
        {
237
                printk("ncp_read_super: invalid wdog socket\n");
238
                sb->s_dev = 0;
239
                return NULL;
240
        }
241
 
242
        if (   (data->message_fd >= NR_OPEN)
243
            || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
244
            || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
245
        {
246
                printk("ncp_read_super: invalid wdog socket\n");
247
                sb->s_dev = 0;
248
                return NULL;
249
        }
250
 
251
        /* We must malloc our own super-block info */
252
        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
253
                                                   GFP_KERNEL);
254
 
255
        if (server == NULL)
256
        {
257
                printk("ncp_read_super: could not alloc ncp_server\n");
258
                return NULL;
259
        }
260
 
261
        ncp_filp->f_count += 1;
262
        wdog_filp->f_count += 1;
263
        msg_filp->f_count += 1;
264
 
265
        lock_super(sb);
266
 
267
        NCP_SBP(sb) = server;
268
 
269
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
270
        sb->s_blocksize_bits = 10;
271
        sb->s_magic = NCP_SUPER_MAGIC;
272
        sb->s_dev = dev;
273
        sb->s_op = &ncp_sops;
274
 
275
        server->ncp_filp    = ncp_filp;
276
        server->wdog_filp   = wdog_filp;
277
        server->msg_filp    = msg_filp;
278
        server->lock        = 0;
279
        server->wait        = NULL;
280
        server->packet      = NULL;
281
        server->buffer_size = 0;
282
        server->conn_status = 0;
283
#ifdef CONFIG_NCPFS_PACKET_SIGNING
284
        server->sign_wanted = 0;
285
        server->sign_active = 0;
286
#endif
287
        server->m = *data;
288
        server->m.file_mode = (server->m.file_mode &
289
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
290
        server->m.dir_mode  = (server->m.dir_mode &
291
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
292
 
293
        /* protect against invalid mount points */
294
        server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';
295
 
296
        server->packet_size = NCP_PACKET_SIZE;
297
        server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
298
 
299
        if (server->packet == NULL)
300
        {
301
                printk("ncpfs: could not alloc packet\n");
302
                error = -ENOMEM;
303
                unlock_super(sb);
304
                goto fail;
305
        }
306
 
307
        /*
308
         * Make the connection to the server
309
         */
310
 
311
        if (ncp_catch_watchdog(server) != 0)
312
        {
313
                printk("ncp_read_super: Could not catch watchdog\n");
314
                error = -EINVAL;
315
                unlock_super(sb);
316
                goto fail;
317
        }
318
 
319
        if (ncp_catch_message(server) != 0)
320
        {
321
                printk("ncp_read_super: Could not catch messages\n");
322
                ncp_dont_catch_watchdog(server);
323
                error = -EINVAL;
324
                unlock_super(sb);
325
                goto fail;
326
        }
327
 
328
        ncp_lock_server(server);
329
        error = ncp_connect(server);
330
        ncp_unlock_server(server);
331
        unlock_super(sb);
332
 
333
        if (error < 0)
334
        {
335
                sb->s_dev = 0;
336
                printk("ncp_read_super: Failed connection, bailing out "
337
                       "(error = %d).\n", -error);
338
                ncp_kfree_s(server->packet, server->packet_size);
339
                ncp_dont_catch_watchdog(server);
340
                goto fail;
341
        }
342
 
343
        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
344
 
345
        ncp_init_root(server);
346
 
347
        if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
348
        {
349
                sb->s_dev = 0;
350
                printk("ncp_read_super: get root inode failed\n");
351
                goto disconnect;
352
        }
353
 
354
#ifdef CONFIG_NCPFS_PACKET_SIGNING
355
        if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
356
                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
357
        {
358
                if (options != NCP_DEFAULT_OPTIONS)
359
                {
360
                        if (ncp_negotiate_size_and_options(server,
361
                                NCP_DEFAULT_BUFSIZE,
362
                                options & 2,
363
                                &(server->buffer_size), &options) != 0)
364
 
365
                        {
366
                                sb->s_dev = 0;
367
                                printk("ncp_read_super: "
368
                                        "could not set options\n");
369
                                goto disconnect;
370
                        }
371
                }
372
                if (options & 2)
373
                        server->sign_wanted = 1;
374
        }
375
        else
376
#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
377
        if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
378
                                     &(server->buffer_size)) != 0)
379
        {
380
                sb->s_dev = 0;
381
                printk("ncp_read_super: could not get bufsize\n");
382
                goto disconnect;
383
        }
384
 
385
        DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
386
 
387
        MOD_INC_USE_COUNT;
388
        return sb;
389
 
390
 disconnect:
391
        ncp_lock_server(server);
392
        ncp_disconnect(server);
393
        ncp_unlock_server(server);
394
        ncp_kfree_s(server->packet, server->packet_size);
395
        ncp_dont_catch_watchdog(server);
396
 fail:
397
        ncp_filp->f_count -= 1;
398
        wdog_filp->f_count -= 1;
399
        msg_filp->f_count -= 1;
400
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
401
        return NULL;
402
}
403
 
404
static void
405
ncp_put_super(struct super_block *sb)
406
{
407
        struct ncp_server *server = NCP_SBP(sb);
408
 
409
        lock_super(sb);
410
 
411
        ncp_lock_server(server);
412
        ncp_disconnect(server);
413
        ncp_unlock_server(server);
414
 
415
        close_fp(server->ncp_filp);
416
 
417
        ncp_dont_catch_watchdog(server);
418
        close_fp(server->wdog_filp);
419
        close_fp(server->msg_filp);
420
 
421
        ncp_free_all_inodes(server);
422
 
423
        ncp_kfree_s(server->packet, server->packet_size);
424
 
425
        sb->s_dev = 0;
426
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
427
        NCP_SBP(sb) = NULL;
428
 
429
        unlock_super(sb);
430
 
431
        MOD_DEC_USE_COUNT;
432
}
433
 
434
/* This routine is called from an interrupt in ncp_msg_data_ready. So
435
 * we have to be careful NOT to sleep here! */
436
void
437
ncp_trigger_message(struct ncp_server *server)
438
{
439
#ifdef CONFIG_KERNELD
440
        char command[ sizeof(server->m.mount_point)
441
                     + sizeof(NCP_MSG_COMMAND) + 2];
442
#endif
443
 
444
        if (server == NULL)
445
        {
446
                printk("ncp_trigger_message: invalid server!\n");
447
                return;
448
        }
449
 
450
        DPRINTK("ncp_trigger_message: on %s\n",
451
                server->m.mount_point);
452
 
453
#ifdef CONFIG_KERNELD
454
        strcpy(command, NCP_MSG_COMMAND);
455
        strcat(command, " ");
456
        strcat(command, server->m.mount_point);
457
        DPRINTK("ksystem: %s\n", command);
458
        ksystem(command, KERNELD_NOWAIT);
459
#endif
460
}
461
 
462
static void
463
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
464
{
465
        struct statfs tmp;
466
 
467
        /* We cannot say how much disk space is left on a mounted
468
           NetWare Server, because free space is distributed over
469
           volumes, and the current user might have disk quotas. So
470
           free space is not that simple to determine. Our decision
471
           here is to err conservatively. */
472
 
473
        tmp.f_type = NCP_SUPER_MAGIC;
474
        tmp.f_bsize = 512;
475
        tmp.f_blocks = 0;
476
        tmp.f_bfree = 0;
477
        tmp.f_bavail = 0;
478
        tmp.f_files = -1;
479
        tmp.f_ffree = -1;
480
        tmp.f_namelen = 12;
481
        memcpy_tofs(buf, &tmp, bufsiz);
482
}
483
 
484
int
485
ncp_notify_change(struct inode *inode, struct iattr *attr)
486
{
487
        int result = 0;
488
        int info_mask;
489
        struct nw_modify_dos_info info;
490
 
491
        if (!ncp_conn_valid(NCP_SERVER(inode)))
492
        {
493
                return -EIO;
494
        }
495
 
496
        if ((result = inode_change_ok(inode, attr)) < 0)
497
                return result;
498
 
499
        if (((attr->ia_valid & ATTR_UID) &&
500
             (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
501
                return -EPERM;
502
 
503
        if (((attr->ia_valid & ATTR_GID) &&
504
             (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
505
                return -EPERM;
506
 
507
        if (((attr->ia_valid & ATTR_MODE) &&
508
             (attr->ia_mode &
509
              ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
510
                return -EPERM;
511
 
512
        info_mask = 0;
513
        memset(&info, 0, sizeof(info));
514
 
515
#if 1 
516
        if ((attr->ia_valid & ATTR_MODE) != 0)
517
        {
518
                if (NCP_ISTRUCT(inode)->attributes & aDIR)
519
                {
520
                        return -EPERM;
521
                }
522
                else
523
                {
524
                        umode_t newmode;
525
 
526
                        info_mask |= DM_ATTRIBUTES;
527
                        newmode=attr->ia_mode;
528
                        newmode &= NCP_SERVER(inode)->m.file_mode;
529
 
530
                        if (newmode & 0222) /* any write bit set */
531
                        {
532
                                info.attributes &= ~0x60001;
533
                        }
534
                        else
535
                        {
536
                                info.attributes |= 0x60001;
537
                        }
538
                }
539
        }
540
#endif
541
 
542
        if ((attr->ia_valid & ATTR_CTIME) != 0)
543
        {
544
                info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
545
                ncp_date_unix2dos(attr->ia_ctime,
546
                                  &(info.creationTime), &(info.creationDate));
547
        }
548
 
549
        if ((attr->ia_valid & ATTR_MTIME) != 0)
550
        {
551
                info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
552
                ncp_date_unix2dos(attr->ia_mtime,
553
                                  &(info.modifyTime), &(info.modifyDate));
554
        }
555
 
556
        if ((attr->ia_valid & ATTR_ATIME) != 0)
557
        {
558
                __u16 dummy;
559
                info_mask |= (DM_LAST_ACCESS_DATE);
560
                ncp_date_unix2dos(attr->ia_ctime,
561
                                  &(dummy), &(info.lastAccessDate));
562
        }
563
 
564
        if (info_mask != 0)
565
        {
566
                if ((result =
567
                     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
568
                                                        NCP_ISTRUCT(inode),
569
                                                        info_mask,
570
                                                        &info)) != 0)
571
                {
572
                        result = -EACCES;
573
 
574
                        if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
575
                        {
576
                                /* NetWare seems not to allow this. I
577
                                   do not know why. So, just tell the
578
                                   user everything went fine. This is
579
                                   a terrible hack, but I do not know
580
                                   how to do this correctly. */
581
                                result = 0;
582
                        }
583
                }
584
        }
585
 
586
        if ((attr->ia_valid & ATTR_SIZE) != 0)
587
        {
588
                int written;
589
 
590
                DPRINTK("ncpfs: trying to change size of %s to %ld\n",
591
                        NCP_ISTRUCT(inode)->entryName, attr->ia_size);
592
 
593
                if ((result = ncp_make_open(inode, O_RDWR)) < 0)
594
                {
595
                        return -EACCES;
596
                }
597
 
598
                ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
599
                          attr->ia_size, 0, "", &written);
600
 
601
                /* According to ndir, the changes only take effect after
602
                   closing the file */
603
                ncp_close_file(NCP_SERVER(inode),
604
                               NCP_FINFO(inode)->file_handle);
605
                NCP_FINFO(inode)->opened = 0;
606
 
607
                result = 0;
608
        }
609
 
610
        ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
611
 
612
        return result;
613
}
614
 
615
#ifdef DEBUG_NCP_MALLOC
616
int ncp_malloced;
617
int ncp_current_malloced;
618
#endif
619
 
620
static struct file_system_type ncp_fs_type = {
621
        ncp_read_super, "ncpfs", 0, NULL
622
        };
623
 
624
int init_ncp_fs(void)
625
{
626
        return register_filesystem(&ncp_fs_type);
627
}
628
 
629
#ifdef MODULE
630
int
631
init_module( void)
632
{
633
        int status;
634
 
635
        DPRINTK("ncpfs: init_module called\n");
636
 
637
#ifdef DEBUG_NCP_MALLOC
638
        ncp_malloced = 0;
639
        ncp_current_malloced = 0;
640
#endif
641
        ncp_init_dir_cache();
642
 
643
        if ((status = init_ncp_fs()) == 0)
644
                register_symtab(0);
645
        return status;
646
}
647
 
648
void
649
cleanup_module(void)
650
{
651
        DPRINTK("ncpfs: cleanup_module called\n");
652
        ncp_free_dir_cache();
653
        unregister_filesystem(&ncp_fs_type);
654
#ifdef DEBUG_NCP_MALLOC
655
        printk("ncp_malloced: %d\n", ncp_malloced);
656
        printk("ncp_current_malloced: %d\n", ncp_current_malloced);
657
#endif
658
}
659
 
660
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.