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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [fs/] [rom/] [v2_0/] [src/] [romfs.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      romfs.c
4
//
5
//      ROM file system
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):           nickg
44
// Contributors:        nickg, richard.panton@3glab.com
45
// Date:                2000-07-25
46
// Purpose:             ROM file system
47
// Description:         This is a ROM filesystem for eCos. It attempts to
48
//                      provide full POSIX-compatible filesystem behaviour
49
//                      while at the same time being efficient in terms of
50
//                      time and space used.
51
//                      
52
//
53
//####DESCRIPTIONEND####
54
//
55
//==========================================================================
56
// 
57
// General Description
58
// ===================
59
// 
60
// This is an implementation of a ROM filesystem for eCos. Its goal is
61
// to provide a working example of a filesystem that provides most of
62
// the required POSIX functionality. And obviously it may also be
63
// useful in its own right.
64
//
65
//
66
// Header
67
// ------
68
//
69
// There is a single header that describes the overall format of the ROMFS
70
// disk. The address of this header is used as the base for all offsets used
71
// in the node and directory structures. It contains the following fields:
72
//
73
// label  - A human readable label for various purposes
74
// fssize - The size in bytes of the entire ROMFS disk
75
// nodes  - A count of the nodes in the disk
76
//
77
// Immediately following thisin memory is the node table, consisting of
78
// 'nodes' repetitions of the node object.
79
//
80
// Nodes
81
// -----
82
//
83
// All files and directories are represented by node objects. Each
84
// romfs_node structure contains the following fields:
85
//
86
// mode   - Node type, file or directory.
87
// nlink  - Number of links to this node. Each directory entry that references
88
//          this node is a link. 
89
// size   - Size of the data in this node in bytes.
90
// ctime  - Creation time of the file (NOT the ROMFS)
91
// data   - Offset of the first data byte for this node from the header
92
//
93
// Directories
94
// -----------
95
//
96
// A directory is a node whose data is a list of directory entries.
97
// These contain the
98
// following fields:
99
//
100
// node    - Index of the node in the romfs_disk table that is referenced by
101
//           this entry. This is present in every directory entry fragment.
102
// next    - Offset of the next name entry.
103
// name    - The filename associated with this link to the node.
104
//
105
// Data Storage
106
// ------------
107
//
108
// Each file has its data stored in a single contiguous memory block
109
// referenced by the offset in the node.
110
//
111
//==========================================================================
112
 
113
#include <pkgconf/system.h>
114
#include <pkgconf/hal.h>
115
#include <pkgconf/kernel.h>
116
#include <pkgconf/io_fileio.h>
117
#include <pkgconf/fs_rom.h>
118
 
119
#include <cyg/kernel/ktypes.h>         // base kernel types
120
#include <cyg/infra/cyg_trac.h>        // tracing macros
121
#include <cyg/infra/cyg_ass.h>         // assertion macros
122
 
123
#include <unistd.h>
124
#include <sys/types.h>
125
#include <fcntl.h>
126
#include <sys/stat.h>
127
#include <errno.h>
128
#include <dirent.h>
129
 
130
#include <stdarg.h>
131
#include <stdio.h>
132
#include <stdlib.h>
133
#include <string.h>
134
 
135
#include <cyg/fileio/fileio.h>
136
 
137
#include <cyg/kernel/kapi.h>
138
#include <cyg/infra/diag.h>
139
 
140
//==========================================================================
141
// Eventually we want to eXecute In Place from the ROM in a protected
142
// environment, so we'll need executables to be aligned to a boundary
143
// suitable for MMU protection. A suitable boundary would be the 4k
144
// boundary in all the CPU architectures I am currently aware of.
145
 
146
// Forward definitions
147
 
148
// Filesystem operations
149
static int romfs_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
150
static int romfs_umount   ( cyg_mtab_entry *mte );
151
static int romfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
152
                             int mode,  cyg_file *fte );
153
static int romfs_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
154
                             cyg_file *fte );
155
static int romfs_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
156
                             cyg_dir *dir_out );
157
static int romfs_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
158
                             struct stat *buf);
159
static int romfs_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
160
                             int key, void *buf, int len );
161
static int romfs_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
162
                             int key, void *buf, int len );
163
 
164
// File operations
165
static int romfs_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
166
static int romfs_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
167
static int romfs_fo_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
168
                                CYG_ADDRWORD data);
169
static int romfs_fo_fsync     (struct CYG_FILE_TAG *fp, int mode );
170
static int romfs_fo_close     (struct CYG_FILE_TAG *fp);
171
static int romfs_fo_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
172
static int romfs_fo_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
173
static int romfs_fo_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
174
 
175
// Directory operations
176
static int romfs_fo_dirread      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
177
static int romfs_fo_dirlseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
178
 
179
 
180
//==========================================================================
181
// Filesystem table entries
182
 
183
// -------------------------------------------------------------------------
184
// Fstab entry.
185
// This defines the entry in the filesystem table.
186
// For simplicity we use _FILESYSTEM synchronization for all accesses since
187
// we should never block in any filesystem operations.
188
 
189
FSTAB_ENTRY( romfs_fste, "romfs", 0,
190
             CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
191
             romfs_mount,
192
             romfs_umount,
193
             romfs_open,
194
             (cyg_fsop_unlink *)cyg_fileio_erofs,
195
             (cyg_fsop_mkdir *)cyg_fileio_erofs,
196
             (cyg_fsop_rmdir *)cyg_fileio_erofs,
197
             (cyg_fsop_rename *)cyg_fileio_erofs,
198
             (cyg_fsop_link *)cyg_fileio_erofs,
199
             romfs_opendir,
200
             romfs_chdir,
201
             romfs_stat,
202
             romfs_getinfo,
203
             romfs_setinfo);
204
 
205
// -------------------------------------------------------------------------
206
// mtab entry.
207
// This defines a single ROMFS loaded into ROM at the configured address
208
//
209
// MTAB_ENTRY(  rom_mte,        // structure name
210
//              "/rom",         // mount point
211
//              "romfs",        // FIlesystem type
212
//              "",             // hardware device
213
//  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS   // Address in ROM
214
//           );
215
 
216
 
217
// -------------------------------------------------------------------------
218
// File operations.
219
// This set of file operations are used for normal open files.
220
 
221
static cyg_fileops romfs_fileops =
222
{
223
    romfs_fo_read,
224
    (cyg_fileop_write *)cyg_fileio_erofs,
225
    romfs_fo_lseek,
226
    romfs_fo_ioctl,
227
    cyg_fileio_seltrue,
228
    romfs_fo_fsync,
229
    romfs_fo_close,
230
    romfs_fo_fstat,
231
    romfs_fo_getinfo,
232
    romfs_fo_setinfo
233
};
234
 
235
// -------------------------------------------------------------------------
236
// Directory file operations.
237
// This set of operations are used for open directories. Most entries
238
// point to error-returning stub functions. Only the read, lseek and
239
// close entries are functional.
240
 
241
static cyg_fileops romfs_dirops =
242
{
243
    romfs_fo_dirread,
244
    (cyg_fileop_write *)cyg_fileio_enosys,
245
    romfs_fo_dirlseek,
246
    (cyg_fileop_ioctl *)cyg_fileio_enosys,
247
    cyg_fileio_seltrue,
248
    (cyg_fileop_fsync *)cyg_fileio_enosys,
249
    romfs_fo_close,
250
    (cyg_fileop_fstat *)cyg_fileio_enosys,
251
    (cyg_fileop_getinfo *)cyg_fileio_enosys,
252
    (cyg_fileop_setinfo *)cyg_fileio_enosys
253
};
254
 
255
//==========================================================================
256
// Data typedefs
257
// Some forward typedefs for the main data structures.
258
 
259
struct romfs_disk;
260
typedef struct romfs_disk romfs_disk;
261
 
262
struct romfs_node;
263
typedef struct romfs_node romfs_node;
264
 
265
struct romfs_dirent;
266
typedef struct romfs_dirent romfs_dirent;
267
 
268
//==========================================================================
269
// File and directory node
270
// This data structure represents a file or directory. 
271
 
272
struct romfs_node
273
{
274
    cyg_uint32          mode;           // 0-3   node type
275
    cyg_ucount32        nlink;          // 4-7   number of links to this node
276
    cyg_uint16          uid;            // 8-9   Owner id
277
    cyg_uint16          gid;            // 10-11 Group id
278
    cyg_uint32          size;           // 12-15 size of file in bytes
279
    cyg_uint32          ctime;          // 16-19 creation status time
280
    cyg_uint32          offset;         // 20-23 offset of data from start of ROMFS
281
    cyg_uint32          pad[2];         // 24-31 padding to align to 32byte boundary
282
};
283
 
284
//==========================================================================
285
// Directory entry.
286
// Variable sized entry containing the name and node of a directory entry
287
 
288
struct romfs_dirent
289
{
290
    cyg_ucount32        node;           // Index of node in romfs_disk structure
291
    cyg_uint32          next;           // Offset from start of directory of
292
                                        // a) the next entry, or 
293
                                        // b) the end of the directory data
294
    char                name[0]; // The name, NUL terminated
295
};
296
 
297
//==========================================================================
298
// ROMFS header
299
// This data structure contains overall information on the ROMFS
300
 
301
struct romfs_disk
302
{
303
    cyg_uint32          magic;          // 0-3   Marks a valid ROMFS entry
304
    cyg_ucount32        nodecount;      // 4-7   Count of nodes in this filesystem
305
    cyg_ucount32        disksize;       // 8-11  Count of bytes in this filesystem
306
    cyg_uint32          dev_id;         // 12-15 ID of disk (put into stat.st_dev)
307
    char                name[16];       // 16-31 Name - pads to 32 bytes
308
    romfs_node          node[0];
309
};
310
 
311
#define ROMFS_MAGIC     0x526f6d2e      // The magic signature word for a romfs
312
#define ROMFS_CIGAM     0x2e6d6f52      // The byte sex is wrong if you see this
313
 
314
//==========================================================================
315
// Directory search data
316
// Parameters for a directory search. The fields of this structure are
317
// updated as we follow a pathname through the directory tree.
318
 
319
struct romfs_dirsearch
320
{
321
    romfs_disk          *disk;          // disk structure
322
    romfs_node          *dir;           // directory to search
323
    const char          *path;          // path to follow
324
    romfs_node          *node;          // Node found
325
    const char          *name;          // last name used
326
    int                 namelen;        // name fragment length
327
    cyg_bool            last;           // last name in path?
328
};
329
 
330
typedef struct romfs_dirsearch romfs_dirsearch;
331
 
332
//==========================================================================
333
// This seems to be the only string function referenced. Define as static
334
// here to avoid having to load the string library
335
 
336
static bool match( const char *a, const char *b, int len )
337
{
338
    for ( ; len > 0 && *a && *b && *a == *b ; a++, b++, len-- )
339
        ;
340
    return ( len == 0 );
341
}
342
 
343
 
344
//==========================================================================
345
// SIMPLE buffer management.
346
// Each node has a data buffer pointer and a size.
347
 
348
// -------------------------------------------------------------------------
349
// findbuffer_node()
350
// return a pointer to the data at the indicated file position.
351
 
352
static int findbuffer_node( romfs_disk *disk,   // header pointer
353
                            romfs_node  *node,  // node pointer
354
                            off_t pos,          // data position to get
355
                            cyg_uint8 **buffer, // returned buffer pointer
356
                            size_t *size)       // returned buffer size
357
{
358
    if ( pos >= node->size || node->size == 0 )
359
    {
360
        // Indicate end of data.
361
        *size = 0;
362
    } else {
363
 
364
        // Calculate the buffer position
365
        *buffer = (cyg_uint8*)disk + node->offset + pos;
366
        *size = node->size-pos;
367
    }
368
 
369
    return ENOERR;
370
}
371
 
372
//==========================================================================
373
// Directory operations
374
 
375
 
376
// -------------------------------------------------------------------------
377
// find_direntry()
378
// Find a directory entry for the name and return a pointer to the first
379
// entry fragment.
380
 
381
static romfs_dirent *find_direntry( romfs_disk *disk, romfs_node *dir, const char *name, int namelen )
382
{
383
    off_t pos = 0;
384
    int err;
385
 
386
    // Loop over all the entries until a match is found or we run out
387
    // of data.
388
    while( pos < dir->size )
389
    {
390
        romfs_dirent *d;
391
        cyg_uint8 *buf;
392
        size_t size;
393
 
394
        err = findbuffer_node( disk, dir, pos, &buf, &size );
395
        if( err != ENOERR || size == 0)
396
            return NULL;
397
 
398
        d = (romfs_dirent *)buf;
399
 
400
        // Is this the directory entry we're looking for?
401
        if ( match( d->name, name, namelen ) )
402
            return d;
403
 
404
        // Otherwise move on to next entry in chain
405
        pos = d->next;
406
    }
407
 
408
    return NULL;
409
}
410
 
411
//==========================================================================
412
// Directory search
413
 
414
// -------------------------------------------------------------------------
415
// init_dirsearch()
416
// Initialize a dirsearch object to start a search
417
 
418
static void init_dirsearch( romfs_dirsearch *ds,
419
                            romfs_disk *disk,
420
                            romfs_node *dir,
421
                            const char *name)
422
{
423
    ds->disk     = disk;
424
    ds->dir      = dir;
425
    ds->path     = name;
426
    ds->node     = dir;
427
    ds->name     = name;
428
    ds->namelen  = 0;
429
    ds->last     = false;
430
}
431
 
432
// -------------------------------------------------------------------------
433
// find_entry()
434
// Search a single directory for the next name in a path and update the
435
// dirsearch object appropriately.
436
 
437
static int find_entry( romfs_dirsearch *ds )
438
{
439
    romfs_node *dir = ds->dir;
440
    const char *name = ds->path;
441
    const char *n = name;
442
    int namelen = 0;
443
    romfs_dirent *d;
444
 
445
    // check that we really have a directory
446
    if( !S_ISDIR(dir->mode) )
447
        return ENOTDIR;
448
 
449
    // Isolate the next element of the path name. 
450
    while( *n != '\0' && *n != '/' )
451
        n++, namelen++;
452
 
453
    // If we terminated on a NUL, set last flag.
454
    if( *n == '\0' )
455
        ds->last = true;
456
 
457
    // update name in dirsearch object
458
    ds->name = name;
459
    ds->namelen = namelen;
460
 
461
    // Here we have the name and its length set up.
462
    // Search the directory for a matching entry
463
 
464
    d = find_direntry( ds->disk, dir, name, namelen );
465
 
466
    if( d == NULL )
467
        return ENOENT;
468
 
469
    // pass back the node we have found
470
    ds->node = &ds->disk->node[d->node];
471
 
472
    return ENOERR;
473
 
474
}
475
 
476
// -------------------------------------------------------------------------
477
// romfs_find()
478
// Main interface to directory search code. This is used in all file
479
// level operations to locate the object named by the pathname.
480
 
481
static int romfs_find( romfs_dirsearch *d )
482
{
483
    int err;
484
 
485
    // Short circuit empty paths
486
    if( *(d->path) == '\0' )
487
        return ENOERR;
488
 
489
    // iterate down directory tree until we find the object
490
    // we want.
491
    for(;;)
492
    {
493
        err = find_entry( d );
494
 
495
        if( err != ENOERR )
496
            return err;
497
 
498
        if( d->last )
499
            return ENOERR;
500
 
501
        // Update dirsearch object to search next directory.
502
        d->dir = d->node;
503
        d->path += d->namelen;
504
        if( *(d->path) == '/' ) d->path++; // skip dirname separators
505
    }
506
}
507
 
508
//==========================================================================
509
// Pathconf support
510
// This function provides support for pathconf() and fpathconf().
511
 
512
static int romfs_pathconf( romfs_node *node, struct cyg_pathconf_info *info )
513
{
514
    int err = ENOERR;
515
 
516
    switch( info->name )
517
    {
518
    case _PC_LINK_MAX:
519
        info->value = LINK_MAX;
520
        break;
521
 
522
    case _PC_MAX_CANON:
523
        info->value = -1;       // not supported
524
        err = EINVAL;
525
        break;
526
 
527
    case _PC_MAX_INPUT:
528
        info->value = -1;       // not supported
529
        err = EINVAL;
530
        break;
531
 
532
    case _PC_NAME_MAX:
533
        info->value = NAME_MAX;
534
        break;
535
 
536
    case _PC_PATH_MAX:
537
        info->value = PATH_MAX;
538
        break;
539
 
540
    case _PC_PIPE_BUF:
541
        info->value = -1;       // not supported
542
        err = EINVAL;
543
        break;
544
 
545
 
546
    case _PC_ASYNC_IO:
547
        info->value = -1;       // not supported
548
        err = EINVAL;
549
        break;
550
 
551
    case _PC_CHOWN_RESTRICTED:
552
        info->value = -1;       // not supported
553
        err = EINVAL;
554
        break;
555
 
556
    case _PC_NO_TRUNC:
557
        info->value = 0;
558
        break;
559
 
560
    case _PC_PRIO_IO:
561
        info->value = 0;
562
        break;
563
 
564
    case _PC_SYNC_IO:
565
        info->value = 0;
566
        break;
567
 
568
    case _PC_VDISABLE:
569
        info->value = -1;       // not supported
570
        err = EINVAL;
571
        break;
572
 
573
    default:
574
        err = EINVAL;
575
        break;
576
    }
577
 
578
    return err;
579
}
580
 
581
//==========================================================================
582
// Filesystem operations
583
 
584
// -------------------------------------------------------------------------
585
// romfs_mount()
586
// Process a mount request. This mainly finds root for the
587
// filesystem.
588
 
589
static int romfs_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
590
{
591
    romfs_disk *disk;
592
 
593
    if ( !mte->data ) {
594
        // If the image address was not in the MTE data word,
595
        if ( mte->devname && mte->devname[0] ) {
596
            // And there's something in the 'hardware device' field,
597
            // then read the address from there.
598
            sscanf( mte->devname, "%p", (char**)&mte->data );
599
        }
600
    }
601
 
602
    if ( !mte->data ) {
603
        // If still no address, try the FSTAB entry data word
604
        mte->data = fste->data;
605
    }
606
 
607
    if ( !mte->data ) {
608
        // If still no address, give up...
609
        return ENOENT;
610
    }
611
 
612
    disk = (romfs_disk *)mte->data;
613
 
614
    // Check the ROMFS magic number to ensure that there's really an fs.
615
    if ( disk->magic == ROMFS_CIGAM ) {
616
        // The disk image has the wrong byte sex!!!
617
        return EIO;
618
    } else if ( disk->magic != ROMFS_MAGIC || disk->nodecount == 0 ) {
619
        // No image found
620
        return ENOENT;
621
    }
622
 
623
    mte->root = (cyg_dir)&disk->node[0];
624
 
625
    return ENOERR;
626
}
627
 
628
// -------------------------------------------------------------------------
629
// romfs_umount()
630
// Unmount the filesystem. This will currently always succeed.
631
 
632
static int romfs_umount   ( cyg_mtab_entry *mte )
633
{
634
    // Clear root pointer
635
    mte->root = CYG_DIR_NULL;
636
 
637
    // That's all folks.
638
 
639
    return ENOERR;
640
}
641
 
642
// -------------------------------------------------------------------------
643
// romfs_open()
644
// Open a file for reading
645
 
646
static int romfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
647
                             int mode,  cyg_file *file )
648
{
649
 
650
    romfs_dirsearch ds;
651
    romfs_node *node = NULL;
652
    int err;
653
 
654
    init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
655
 
656
    err = romfs_find( &ds );
657
 
658
    if( err == ENOENT )
659
    {
660
        return ENOENT;
661
    }
662
    else if( err == ENOERR )
663
    {
664
        // The node exists. If the O_CREAT and O_EXCL bits are set, we
665
        // must fail the open.
666
 
667
        if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
668
            err = EEXIST;
669
        else node = ds.node;
670
    }
671
 
672
    if( err == ENOERR && (mode & O_TRUNC ) )
673
    {
674
        // If the O_TRUNC bit is set we must fail the open
675
 
676
        err = EPERM;
677
    }
678
 
679
    if( err != ENOERR ) return err;
680
 
681
    // Check that we actually have a file here
682
    if( S_ISDIR(node->mode) ) return EISDIR;
683
 
684
    // Initialize the file object
685
 
686
    file->f_flag        |= mode & CYG_FILE_MODE_MASK;
687
    file->f_type        = CYG_FILE_TYPE_FILE;
688
    file->f_ops         = &romfs_fileops;
689
    file->f_offset      = 0;
690
    file->f_data        = (CYG_ADDRWORD)node;
691
    file->f_xops        = 0;
692
 
693
    return ENOERR;
694
}
695
 
696
// -------------------------------------------------------------------------
697
// romfs_opendir()
698
// Open a directory for reading.
699
 
700
static int romfs_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
701
                             cyg_file *file )
702
{
703
    romfs_dirsearch ds;
704
    int err;
705
 
706
    init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
707
 
708
    err = romfs_find( &ds );
709
 
710
    if( err != ENOERR ) return err;
711
 
712
    // check it is really a directory.
713
    if( !S_ISDIR(ds.node->mode) ) return ENOTDIR;
714
 
715
    // Initialize the file object, setting the f_ops field to a
716
    // special set of file ops.
717
 
718
    file->f_type        = CYG_FILE_TYPE_FILE;
719
    file->f_ops         = &romfs_dirops;
720
    file->f_offset      = 0;
721
    file->f_data        = (CYG_ADDRWORD)ds.node;
722
    file->f_xops        = 0;
723
 
724
    return ENOERR;
725
 
726
}
727
 
728
// -------------------------------------------------------------------------
729
// romfs_chdir()
730
// Change directory support.
731
 
732
static int romfs_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
733
                             cyg_dir *dir_out )
734
{
735
    if( dir_out != NULL )
736
    {
737
        // This is a request to get a new directory pointer in
738
        // *dir_out.
739
 
740
        romfs_dirsearch ds;
741
        int err;
742
 
743
        init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
744
 
745
        err = romfs_find( &ds );
746
 
747
        if( err != ENOERR ) return err;
748
 
749
        // check it is a directory
750
        if( !S_ISDIR(ds.node->mode) )
751
            return ENOTDIR;
752
 
753
        // Pass it out
754
        *dir_out = (cyg_dir)ds.node;
755
    }
756
    // If no output dir is required, this means that the mte and
757
    // dir arguments are the current cdir setting and we should
758
    // forget this fact. Do nothing in ROMFS.
759
 
760
    return ENOERR;
761
}
762
 
763
// -------------------------------------------------------------------------
764
// romfs_stat()
765
// Get struct stat info for named object.
766
 
767
static int romfs_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
768
                             struct stat *buf)
769
{
770
    romfs_dirsearch ds;
771
    int err;
772
    romfs_disk *disk = (romfs_disk *)mte->data;
773
 
774
    init_dirsearch( &ds, disk, (romfs_node *)dir, name );
775
 
776
    err = romfs_find( &ds );
777
 
778
    if( err != ENOERR ) return err;
779
 
780
    // Fill in the status
781
    buf->st_mode        = ds.node->mode;
782
    buf->st_ino         = (ino_t)(ds.node - &disk->node[0]);
783
    buf->st_dev         = (dev_t)disk->dev_id;
784
    buf->st_nlink       = ds.node->nlink;
785
    buf->st_uid         = ds.node->uid;
786
    buf->st_gid         = ds.node->gid;
787
    buf->st_size        = ds.node->size;
788
    buf->st_atime       = ds.node->ctime;
789
    buf->st_mtime       = ds.node->ctime;
790
    buf->st_ctime       = ds.node->ctime;
791
 
792
    return err;
793
}
794
 
795
// -------------------------------------------------------------------------
796
// romfs_getinfo()
797
// Getinfo. Currently only support pathconf().
798
 
799
static int romfs_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
800
                             int key, void *buf, int len )
801
{
802
    romfs_dirsearch ds;
803
    int err;
804
 
805
    init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
806
 
807
    err = romfs_find( &ds );
808
 
809
    if( err != ENOERR ) return err;
810
 
811
    switch( key )
812
    {
813
    case FS_INFO_CONF:
814
        err = romfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
815
        break;
816
 
817
    default:
818
        err = EINVAL;
819
    }
820
    return err;
821
}
822
 
823
// -------------------------------------------------------------------------
824
// romfs_setinfo()
825
// Setinfo. Nothing to support here at present.
826
 
827
static int romfs_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
828
                             int key, void *buf, int len )
829
{
830
    // No setinfo keys supported at present
831
 
832
    return EINVAL;
833
}
834
 
835
 
836
//==========================================================================
837
// File operations
838
 
839
// -------------------------------------------------------------------------
840
// romfs_fo_read()
841
// Read data from the file.
842
 
843
static int romfs_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
844
{
845
    romfs_node *node = (romfs_node *)fp->f_data;
846
    int i;
847
    off_t pos = fp->f_offset;
848
    ssize_t resid = uio->uio_resid;
849
 
850
    // Loop over the io vectors until there are none left
851
    for( i = 0; i < uio->uio_iovcnt; i++ )
852
    {
853
        cyg_iovec *iov = &uio->uio_iov[i];
854
        char *buf = (char *)iov->iov_base;
855
        off_t len = iov->iov_len;
856
 
857
        // Loop over each vector filling it with data from the file.
858
        while( len > 0 && pos < node->size )
859
        {
860
            cyg_uint8 *fbuf;
861
            size_t bsize;
862
            off_t l = len;
863
            int err;
864
 
865
            // Get a pointer to the data at offset _pos_.
866
            err = findbuffer_node( (romfs_disk *)fp->f_mte->data, node, pos, &fbuf, &bsize );
867
 
868
            if( err != ENOERR )
869
                return err;
870
 
871
            // adjust size to end of file if necessary
872
            if( l > node->size-pos )
873
                l = node->size-pos;
874
 
875
            // adjust size to the amount of contiguous data we can see
876
            // at present.
877
            if( l > bsize )
878
                l = bsize;
879
 
880
            // copy data out
881
            memcpy( buf, fbuf, l );
882
 
883
            // Update working vars
884
            len -= l;
885
            buf += l;
886
            pos += l;
887
            resid -= l;
888
        }
889
    }
890
 
891
    // We successfully read some data
892
    // Update the file offset and transfer residue.
893
 
894
    uio->uio_resid = resid;
895
    fp->f_offset = pos;
896
 
897
    return ENOERR;
898
}
899
 
900
// -------------------------------------------------------------------------
901
// romfs_fo_lseek()
902
// Seek to a new file position.
903
 
904
static int romfs_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *apos, int whence )
905
{
906
    romfs_node *node = (romfs_node *)fp->f_data;
907
    off_t pos = *apos;
908
 
909
    switch( whence )
910
    {
911
    case SEEK_SET:
912
        // Pos is already where we want to be.
913
        break;
914
 
915
    case SEEK_CUR:
916
        // Add pos to current offset.
917
        pos += fp->f_offset;
918
        break;
919
 
920
    case SEEK_END:
921
        // Add pos to file size.
922
        pos += node->size;
923
        break;
924
 
925
    default:
926
        return EINVAL;
927
    }
928
 
929
    // Check that pos is still within current file size, or at the
930
    // very end.
931
    if( pos < 0 || pos > node->size )
932
        return EINVAL;
933
 
934
    // All OK, set fp offset and return new position.
935
    *apos = fp->f_offset = pos;
936
 
937
    return ENOERR;
938
}
939
 
940
// -------------------------------------------------------------------------
941
// romfs_fo_ioctl()
942
// Handle ioctls. Currently none are defined.
943
 
944
static int romfs_fo_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
945
                                CYG_ADDRWORD data)
946
{
947
    // No Ioctls currenly defined.
948
 
949
    return EINVAL;
950
}
951
 
952
// -------------------------------------------------------------------------
953
// romfs_fo_fsync().
954
// Force the file out to data storage.
955
 
956
static int romfs_fo_fsync     (struct CYG_FILE_TAG *fp, int mode )
957
{
958
    // Data is always permanently where it belongs, nothing to do
959
    // here.
960
 
961
    return ENOERR;
962
}
963
 
964
// -------------------------------------------------------------------------
965
// romfs_fo_close()
966
// Close a file. We just clear out the data pointer.
967
 
968
static int romfs_fo_close     (struct CYG_FILE_TAG *fp)
969
{
970
    fp->f_data = 0;     // zero data pointer
971
 
972
    return ENOERR;
973
}
974
 
975
// -------------------------------------------------------------------------
976
//romfs_fo_fstat()
977
// Get file status.
978
 
979
static int romfs_fo_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf )
980
{
981
    romfs_node *node = (romfs_node *)fp->f_data;
982
    romfs_disk *disk = (romfs_disk*)(fp->f_mte->data);
983
 
984
    // Fill in the status
985
    buf->st_mode        = node->mode;
986
    buf->st_ino         = (ino_t)(node - &disk->node[0]);
987
    buf->st_dev         = disk->dev_id;
988
    buf->st_nlink       = node->nlink;
989
    buf->st_uid         = node->uid;
990
    buf->st_gid         = node->gid;
991
    buf->st_size        = node->size;
992
    buf->st_atime       = node->ctime;
993
    buf->st_mtime       = node->ctime;
994
    buf->st_ctime       = node->ctime;
995
 
996
    return ENOERR;
997
}
998
 
999
// -------------------------------------------------------------------------
1000
// romfs_fo_getinfo()
1001
// Get info. Currently only supports fpathconf().
1002
 
1003
static int romfs_fo_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1004
{
1005
    romfs_node *node = (romfs_node *)fp->f_data;
1006
    int err;
1007
 
1008
    switch( key )
1009
    {
1010
    case FS_INFO_CONF:
1011
        err = romfs_pathconf( node, (struct cyg_pathconf_info *)buf );
1012
        break;
1013
 
1014
    default:
1015
        err = EINVAL;
1016
    }
1017
    return err;
1018
}
1019
 
1020
// -------------------------------------------------------------------------
1021
// romfs_fo_setinfo()
1022
// Set info. Nothing supported here.
1023
 
1024
static int romfs_fo_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1025
{
1026
    // No setinfo key supported at present
1027
 
1028
    return ENOERR;
1029
}
1030
 
1031
 
1032
//==========================================================================
1033
// Directory operations
1034
 
1035
// -------------------------------------------------------------------------
1036
// romfs_fo_dirread()
1037
// Read a single directory entry from a file.
1038
 
1039
static int romfs_fo_dirread      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1040
{
1041
    romfs_node *dir = (romfs_node *)fp->f_data;
1042
    off_t pos = fp->f_offset;
1043
    int err = ENOERR;
1044
    struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
1045
    char *nbuf = ent->d_name;
1046
    int nlen = sizeof(ent->d_name)-1;
1047
    off_t len = uio->uio_iov[0].iov_len;
1048
    romfs_dirent *d = NULL;
1049
    cyg_uint8 *buf;
1050
    size_t size;
1051
    int i;
1052
 
1053
    if( len < sizeof(struct dirent) )
1054
        return EINVAL;
1055
 
1056
    // Get the next entry
1057
    err = findbuffer_node( (romfs_disk *)fp->f_mte->data, dir, pos, &buf, &size );
1058
    if( err != ENOERR || size == 0 || pos >= dir->size )
1059
        return err;
1060
 
1061
    d = (romfs_dirent *)buf;
1062
 
1063
    for ( i = 0 ; i < nlen && d->name[i] ; i++, nbuf++ )
1064
        *nbuf = d->name[i];
1065
 
1066
    // A successful read. Terminate the entry name with a NUL, set the
1067
    // residue and set the file offset to restart at the next
1068
    // directory entry.
1069
 
1070
    *nbuf = '\0';
1071
    uio->uio_resid -= sizeof(struct dirent);
1072
    fp->f_offset = d->next;
1073
 
1074
    return ENOERR;
1075
}
1076
 
1077
// -------------------------------------------------------------------------
1078
// romfs_fo_dirlseek()
1079
// Seek directory to start.
1080
 
1081
static int romfs_fo_dirlseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
1082
{
1083
    // Only allow SEEK_SET to zero
1084
 
1085
    if( whence != SEEK_SET || *pos != 0)
1086
        return EINVAL;
1087
 
1088
    *pos = fp->f_offset = 0;
1089
 
1090
    return ENOERR;
1091
}
1092
 
1093
// -------------------------------------------------------------------------
1094
// EOF romfs.c

powered by: WebSVN 2.1.0

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