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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [fileio/] [v2_0/] [src/] [file.cxx] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      file.cxx
4
//
5
//      Fileio file operations
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
45
// Date:                2000-05-25
46
// Purpose:             Fileio file operations
47
// Description:         These are the functions that operate on files as a whole,
48
//                      such as open(), creat(), mkdir() etc.
49
//              
50
//              
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include <pkgconf/hal.h>
57
#include <pkgconf/io_fileio.h>
58
#include <pkgconf/isoinfra.h>
59
 
60
#include <cyg/infra/cyg_trac.h>        // tracing macros
61
#include <cyg/infra/cyg_ass.h>         // assertion macros
62
 
63
#include <string.h>                    // string functions
64
#include <dirent.h>
65
#include <stdio.h>                     // stdin, stdout, stderr
66
 
67
#include "fio.h"                       // Private header
68
 
69
//==========================================================================
70
// Implement filesystem locking protocol. 
71
 
72
#define LOCK_FS( _mte_ )  {                             \
73
   CYG_ASSERT(_mte_ != NULL, "Bad mount table entry");  \
74
   cyg_fs_lock( _mte_, (_mte_)->fs->syncmode);          \
75
}
76
 
77
#define UNLOCK_FS( _mte_ ) cyg_fs_unlock( _mte_, (_mte_)->fs->syncmode)
78
 
79
//==========================================================================
80
// A local strcpy clone that returns a pointer to the end of the copied
81
// string, not the beginning.
82
 
83
static char *my_strcpy( char *s1, const char *s2 )
84
{
85
    while( (*s1++ = *s2++) != 0);
86
    return s1-1;
87
}
88
 
89
//==========================================================================
90
// Compare a pathname fragment with an element in a pathname. This
91
// deals with zero or separator termination and avoids substring
92
// matches.
93
 
94
static int pathcmp( const char *path, const char *name )
95
{
96
    while( *path == *name && *path != '\0' )
97
        path++, name++;
98
    if( *name != '\0' ) return false;
99
    if( *path == '/' || *path == '\0' ) return true;
100
    return false;
101
}
102
 
103
//==========================================================================
104
// CWD support
105
 
106
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
107
 
108
// buffer for storing CWD path
109
static char cwd[PATH_MAX];
110
static size_t cwd_size = 0;
111
 
112
 
113
static void update_cwd( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
114
{
115
    char *p = cwd;
116
 
117
    if( mte != cdir_mtab_entry || dir != cdir_dir )
118
    {
119
        // Here, the path is relative to the root of the filesystem,
120
        // or in a totally new filesystem, initialize the cwd with the
121
        // mount point name of the filesystem.
122
 
123
        p = my_strcpy( p, mte->name );
124
    }
125
    else p = cwd+cwd_size;
126
 
127
    // We must now copy the path into the cwd buffer while dealing
128
    // with any "." and ".."  components textually.
129
 
130
    while( *path != '\0' )
131
    {
132
        // skip any stray directory separators.
133
        if( *path == '/' ) path++;
134
 
135
        // Look for a "." entry and just ignore it.
136
        if( pathcmp( path, "." ) )
137
        {
138
            path++;
139
            continue;
140
        }
141
 
142
        // Look for a ".." entry. If found, chew off the last cwd
143
        // entry.
144
        if( pathcmp( path, ".." ) )
145
        {
146
            while( *(--p) != '/' );     // back up to last '/'
147
            path += 2;                  // skip "..".
148
            continue;
149
        }
150
 
151
        // Otherwise just copy the name fragment over to the cwd.
152
 
153
        if( *(p-1) != '/' )
154
            *p++ = '/';        // add a directory separator
155
        while( *path != '/' && *path != '\0' )
156
            *p++ = *path++;
157
 
158
    }
159
 
160
    // Zero terminate the cwd.
161
    *p = '\0';
162
 
163
    // update size
164
    cwd_size = p-cwd;
165
}
166
 
167
#else
168
 
169
#ifdef CYGPKG_KERNEL
170
static Cyg_Mutex getcwd_lock CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
171
#endif
172
 
173
#endif
174
 
175
 
176
//==========================================================================
177
// Open a file
178
 
179
__externC int open( const char *path, int oflag, ... )
180
{
181
    FILEIO_ENTRY();
182
 
183
    // we want to be sure we pull in stdin/out/err, so they can be
184
    // assigned to fds 0, 1 and 2
185
#ifdef CYGINT_ISO_STDIO_STREAMS
186
    CYG_REFERENCE_OBJECT(stdin);
187
    CYG_REFERENCE_OBJECT(stdout);
188
    CYG_REFERENCE_OBJECT(stderr);
189
#endif
190
 
191
    CYG_CANCELLATION_POINT;
192
 
193
    int ret = 0;
194
    int fd;
195
    cyg_file *file;
196
    cyg_mtab_entry *mte = cdir_mtab_entry;
197
    cyg_dir dir = cdir_dir;
198
    const char *name = path;
199
 
200
    // At least one of O_RDONLY, O_WRONLY, O_RDWR must be provided
201
    if( (oflag & O_RDWR) == 0 )
202
        FILEIO_RETURN(EINVAL);
203
 
204
    fd = cyg_fd_alloc(0);
205
 
206
    if( fd < 0 )
207
        FILEIO_RETURN(EMFILE);
208
 
209
    file = cyg_file_alloc();
210
 
211
    if( file == NULL )
212
    {
213
        cyg_fd_free(fd);
214
        FILEIO_RETURN(ENFILE);
215
    }
216
 
217
    ret = cyg_mtab_lookup( &dir, &name, &mte );
218
 
219
    if( 0 != ret )
220
    {
221
        cyg_fd_free(fd);
222
        cyg_file_free(file);
223
        FILEIO_RETURN(ENOENT);
224
    }
225
 
226
    LOCK_FS( mte );
227
 
228
    ret = mte->fs->open( mte, dir, name, oflag, file );
229
 
230
    UNLOCK_FS( mte );
231
 
232
    if( 0 != ret )
233
    {
234
        cyg_fd_free(fd);
235
        cyg_file_free(file);
236
        FILEIO_RETURN(ret);
237
    }
238
 
239
    file->f_mte = mte;
240
    file->f_syncmode = mte->fs->syncmode;
241
 
242
    cyg_fd_assign( fd, file );
243
 
244
    FILEIO_RETURN_VALUE(fd);
245
}
246
 
247
//==========================================================================
248
// create a file
249
 
250
__externC int creat( const char *path, mode_t mode )
251
{
252
    return open( path, O_WRONLY | O_CREAT | O_TRUNC, mode );
253
}
254
 
255
 
256
//==========================================================================
257
// Unlink/remove a file
258
 
259
__externC int unlink( const char *path )
260
{
261
    FILEIO_ENTRY();
262
 
263
    int ret = 0;
264
    cyg_mtab_entry *mte = cdir_mtab_entry;
265
    cyg_dir dir = cdir_dir;
266
    const char *name = path;
267
 
268
    ret = cyg_mtab_lookup( &dir, &name, &mte );
269
 
270
    if( 0 != ret )
271
        FILEIO_RETURN(ENOENT);
272
 
273
    LOCK_FS( mte );
274
 
275
    ret = mte->fs->unlink( mte, dir, name );
276
 
277
    UNLOCK_FS( mte );
278
 
279
    FILEIO_RETURN(ret);
280
}
281
 
282
//==========================================================================
283
// Make a directory
284
 
285
__externC int mkdir( const char *path, mode_t mode )
286
{
287
    FILEIO_ENTRY();
288
 
289
    int ret = 0;
290
    cyg_mtab_entry *mte = cdir_mtab_entry;
291
    cyg_dir dir = cdir_dir;
292
    const char *name = path;
293
 
294
    mode=mode;
295
 
296
    ret = cyg_mtab_lookup( &dir, &name, &mte );
297
 
298
    if( 0 != ret )
299
        FILEIO_RETURN(ENOENT);
300
 
301
    LOCK_FS( mte );
302
 
303
    ret = mte->fs->mkdir( mte, dir, name );
304
 
305
    UNLOCK_FS( mte );
306
 
307
    FILEIO_RETURN(ret);
308
}
309
 
310
//==========================================================================
311
// Remove a directory
312
 
313
__externC int rmdir( const char *path )
314
{
315
    FILEIO_ENTRY();
316
 
317
    int ret = 0;
318
    cyg_mtab_entry *mte = cdir_mtab_entry;
319
    cyg_dir dir = cdir_dir;
320
    const char *name = path;
321
 
322
    ret = cyg_mtab_lookup( &dir, &name, &mte );
323
 
324
    if( 0 != ret )
325
        FILEIO_RETURN(ENOENT);
326
 
327
    LOCK_FS( mte );
328
 
329
    ret = mte->fs->rmdir( mte, dir, name );
330
 
331
    UNLOCK_FS( mte );
332
 
333
    FILEIO_RETURN(ret);
334
}
335
 
336
//==========================================================================
337
// Rename a file
338
 
339
__externC int rename( const char *path1, const char *path2 )
340
{
341
    FILEIO_ENTRY();
342
 
343
    int ret = 0;
344
    cyg_mtab_entry *mte1 = cdir_mtab_entry;
345
    cyg_mtab_entry *mte2 = cdir_mtab_entry;
346
    cyg_dir dir1 = cdir_dir;
347
    cyg_dir dir2 = cdir_dir;
348
    const char *name1 = path1;
349
    const char *name2 = path2;
350
 
351
    ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
352
 
353
    if( 0 != ret )
354
        FILEIO_RETURN(ENOENT);
355
 
356
    ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
357
 
358
    if( 0 != ret )
359
        FILEIO_RETURN(ENOENT);
360
 
361
    // Cannot rename between different filesystems
362
    if( mte1 != mte2 )
363
        FILEIO_RETURN(EXDEV);
364
 
365
    LOCK_FS( mte1 );
366
 
367
    ret = mte1->fs->rename( mte1, dir1, name1, dir2, name2 );
368
 
369
    UNLOCK_FS( mte1 );
370
 
371
    FILEIO_RETURN(ret);
372
}
373
 
374
//==========================================================================
375
// Create a link from an existing file (path1) to a new one (path2)
376
 
377
__externC int link( const char *path1, const char *path2 )
378
{
379
    FILEIO_ENTRY();
380
 
381
    int ret = 0;
382
    cyg_mtab_entry *mte1 = cdir_mtab_entry;
383
    cyg_mtab_entry *mte2 = cdir_mtab_entry;
384
    cyg_dir dir1 = cdir_dir;
385
    cyg_dir dir2 = cdir_dir;
386
    const char *name1 = path1;
387
    const char *name2 = path2;
388
 
389
    ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
390
 
391
    if( 0 != ret )
392
        FILEIO_RETURN(ENOENT);
393
 
394
    ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
395
 
396
    if( 0 != ret )
397
        FILEIO_RETURN(ENOENT);
398
 
399
    // Cannot hard-link between different filesystems
400
    if( mte1 != mte2 )
401
        FILEIO_RETURN(EXDEV);
402
 
403
    LOCK_FS( mte1 );
404
 
405
    ret = mte1->fs->link( mte1, dir1, name1, dir2, name2, CYG_FSLINK_HARD );
406
 
407
    UNLOCK_FS( mte1 );
408
 
409
    FILEIO_RETURN(ret);
410
}
411
 
412
//==========================================================================
413
// Change current directory
414
 
415
__externC int chdir( const char *path )
416
{
417
    FILEIO_ENTRY();
418
 
419
    int ret = 0;
420
    cyg_mtab_entry *mte = cdir_mtab_entry;
421
    cyg_dir dir = cdir_dir;
422
    cyg_dir newdir;
423
    const char *name = path;
424
 
425
    ret = cyg_mtab_lookup( &dir, &name, &mte );
426
 
427
    if( 0 != ret )
428
        FILEIO_RETURN(ENOENT);
429
 
430
    LOCK_FS(mte);
431
 
432
    ret = mte->fs->chdir( mte, dir, name, &newdir );
433
 
434
    UNLOCK_FS(mte);
435
 
436
    if( 0 != ret )
437
        FILEIO_RETURN(ret);
438
 
439
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
440
    update_cwd( mte, dir, name );
441
#endif
442
 
443
    if( cdir_mtab_entry != NULL && cdir_dir != CYG_DIR_NULL )
444
    {
445
        // Now detach from current cdir. We call the current directory's
446
        // chdir routine with a NULL dir_out pointer.
447
 
448
        LOCK_FS(cdir_mtab_entry);
449
 
450
        ret = cdir_mtab_entry->fs->chdir( cdir_mtab_entry, cdir_dir, NULL, NULL );
451
 
452
        UNLOCK_FS(cdir_mtab_entry);
453
 
454
        // We really shouldn't get an error here.
455
        if( 0 != ret )
456
            FILEIO_RETURN(ret);
457
    }
458
 
459
    cdir_mtab_entry = mte;
460
    cdir_dir = newdir;
461
 
462
    FILEIO_RETURN(ENOERR);
463
}
464
 
465
//==========================================================================
466
// Get file statistics
467
 
468
__externC int stat( const char *path, struct stat *buf )
469
{
470
    FILEIO_ENTRY();
471
 
472
    int ret = 0;
473
    cyg_mtab_entry *mte = cdir_mtab_entry;
474
    cyg_dir dir = cdir_dir;
475
    const char *name = path;
476
 
477
    ret = cyg_mtab_lookup( &dir, &name, &mte );
478
 
479
    if( 0 != ret )
480
        FILEIO_RETURN(ENOENT);
481
 
482
    LOCK_FS( mte );
483
 
484
    ret = mte->fs->stat( mte, dir, name, buf );
485
 
486
    UNLOCK_FS( mte );
487
 
488
    FILEIO_RETURN(ret);
489
}
490
 
491
//==========================================================================
492
// Get file configurable pathname variables
493
 
494
__externC long pathconf( const char *path, int vname )
495
{
496
    FILEIO_ENTRY();
497
 
498
    int ret = 0;
499
    cyg_mtab_entry *mte = cdir_mtab_entry;
500
    cyg_dir dir = cdir_dir;
501
    const char *name = path;
502
 
503
    ret = cyg_mtab_lookup( &dir, &name, &mte );
504
 
505
    if( 0 != ret )
506
        FILEIO_RETURN(ENOENT);
507
 
508
    struct cyg_pathconf_info info;
509
 
510
    info.name = vname;
511
    info.value = 0;
512
 
513
    LOCK_FS( mte );
514
 
515
    ret = mte->fs->getinfo( mte, dir, name,
516
                            FS_INFO_CONF, (char *)&info, sizeof(info) );
517
 
518
    UNLOCK_FS( mte );
519
 
520
    if( 0 != ret )
521
        FILEIO_RETURN(ret);
522
 
523
    FILEIO_RETURN_VALUE(info.value);
524
}
525
 
526
//==========================================================================
527
// Access() function.
528
// This simply piggybacks onto stat().
529
 
530
extern int      access(const char *path, int amode)
531
{
532
    FILEIO_ENTRY();
533
 
534
    int ret;
535
    struct stat buf;
536
 
537
    ret = stat( path, &buf );
538
 
539
    // Translate not found into EACCES if the F_OK bit is
540
    // set.
541
    if( (amode & F_OK) && (ret < 0) && (errno == ENOENT) )
542
        FILEIO_RETURN(EACCES);
543
 
544
    // All other errors go straight back to the user.
545
    if( ret < 0 )
546
        FILEIO_RETURN_VALUE(ret);
547
 
548
    // At present we do not have any access modes, so there is nothing
549
    // to test.  Just return success for all access modes.
550
 
551
    FILEIO_RETURN(ENOERR);
552
}
553
 
554
//==========================================================================
555
// getcwd()
556
 
557
__externC char *getcwd( char *buf, size_t size )
558
{
559
    FILEIO_ENTRY();
560
 
561
    int err = ENOERR;
562
    cyg_mtab_entry *mte = cdir_mtab_entry;
563
    cyg_dir dir = cdir_dir;
564
    cyg_getcwd_info info;
565
 
566
    if( size == 0 )
567
    {
568
        errno = EINVAL;
569
        FILEIO_RETURN_VALUE(NULL);
570
    }
571
 
572
    info.buf = buf;
573
    info.size = size;
574
 
575
    LOCK_FS( mte );
576
 
577
    err = mte->fs->getinfo( mte, dir, "",
578
                            FS_INFO_GETCWD, (char *)&info, sizeof(info) );
579
 
580
    UNLOCK_FS( mte );
581
 
582
    if( err == ENOERR )
583
        FILEIO_RETURN_VALUE(buf);
584
 
585
    // Attempting to use filesystem support for getcwd() has
586
    // failed.
587
 
588
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
589
 
590
    // If this option is set, the current directory path has been
591
    // tracked in chdir(). Just report that value here.
592
 
593
    if( size < cwd_size+1 )
594
    {
595
        errno = ERANGE;
596
        FILEIO_RETURN_VALUE(NULL);
597
    }
598
 
599
    char *p = my_strcpy( buf, cwd );
600
    *p = '\0';
601
 
602
#else
603
 
604
    // As a fallback we try to use ".." entries in the directory tree
605
    // to climb back up to the root.  Because we cannot assume that
606
    // any filesystem can handle more than one directory pointer we
607
    // have to do the climbing textually, by manufacturing a path name
608
    // consisting of ".."s. At each level we then scan the parent
609
    // directory looking for the entry for the lower level directory
610
    // by matching st_ino values. This is not guaranteed to work at
611
    // all since there is no requirement on filesystems to support "."
612
    // and "..", or for them to report distinct inode values in
613
    // stat().
614
 
615
    static char ddbuf[PATH_MAX];
616
    char *p = buf+size-1;
617
    int ddbufpos;
618
 
619
    // Claim lock to serialize use of ddbuf.
620
    FILEIO_MUTEX_LOCK(getcwd_lock);
621
 
622
    // Initialize ddbuf with ".".
623
    ddbuf[0] = '.';
624
    ddbuf[1] = '\0';
625
    ddbufpos = 1;
626
 
627
    // Start result buffer with a zero terminator. We accumulate the
628
    // path name in the top end of the result buffer.
629
    *p = '\0';
630
 
631
    for(;;)
632
    {
633
        struct stat sdbuf;
634
        struct stat sddbuf;
635
 
636
        // Get status for "." and "..". If the filesystem does not
637
        // support these, then this whole function will fail here.
638
 
639
        err = stat( ddbuf, &sdbuf );
640
        if( err < 0 ) break;
641
 
642
        ddbuf[ddbufpos++] = '/';
643
        ddbuf[ddbufpos++] = '.';
644
        ddbuf[ddbufpos++] = '.';
645
        ddbuf[ddbufpos] = '\0';
646
 
647
        err = stat( ddbuf, &sddbuf );
648
        if( err < 0 ) break;
649
 
650
        // See whether we are at the root. This will be true when
651
        // the inode numbers of "." and ".." are the same.
652
        if( sdbuf.st_ino == sddbuf.st_ino )
653
            break;
654
 
655
        // We now need to find an entry in the ".." directory that
656
        // matches the inode number of ".".
657
 
658
        struct dirent de;
659
        DIR *d = opendir( ddbuf );
660
        if( d == NULL )
661
        {
662
            err = -1;
663
            break;
664
        }
665
 
666
        for(;;)
667
        {
668
            struct dirent *res;
669
            struct stat objstat;
670
            int i;
671
 
672
            err = readdir_r( d, &de, &res );
673
            if( err < 0 || res == NULL ) break;
674
 
675
            // Skip "." and ".." entries.
676
            if( pathcmp( de.d_name, "." ) || pathcmp( de.d_name, ".." ) )
677
                continue;
678
 
679
            // Tack the name of the directory entry on to the ddbuf
680
            // and stat the object.
681
 
682
            ddbuf[ddbufpos] = '/';
683
            for( i = 0; de.d_name[i] != '\0'; i++ )
684
                ddbuf[ddbufpos+i+1] = de.d_name[i];
685
            ddbuf[ddbufpos+i+1] = '\0';
686
 
687
            // Take a look at it
688
            err = stat( ddbuf, &objstat );
689
            if( err < 0 ) break;
690
 
691
            // Cast out directories
692
            if( !S_ISDIR(objstat.st_mode) )
693
                continue;
694
 
695
            // We have a directory. Compare its inode with that of "."
696
            // and if they are the same, we have found our entry.
697
 
698
            if( sdbuf.st_ino == objstat.st_ino )
699
                break;
700
        }
701
 
702
        ddbuf[ddbufpos] = '\0'; // reterminate ddbuf
703
 
704
        closedir( d );
705
 
706
        // Halt on any errors.
707
        if( err < 0 )
708
            break;
709
 
710
        // Here de contains the name of the directory entry in ".."
711
        // that has the same inode as ".". Add the name to the path we
712
        // are accumulating in the buffer.
713
 
714
        char *q = de.d_name;
715
        while( *q != '\0' ) q++;        // skip to end of name
716
 
717
        do
718
        {
719
            *--p = *--q;
720
        } while( q != de.d_name );
721
 
722
        *--p = '/';                     // add a separator
723
    }
724
 
725
    // We have finished using ddbuf now.
726
    FILEIO_MUTEX_UNLOCK(getcwd_lock);
727
 
728
    if( err < 0 )
729
        FILEIO_RETURN_VALUE(NULL);
730
 
731
    // We have the directory path in the top end of the buffer.  Add
732
    // the mount point name at the beginning and copy the rest of the
733
    // name down.
734
 
735
    char *bp = buf;
736
 
737
    bp = my_strcpy( bp, mte->name );
738
 
739
    // Sort out the separators between the mount name and the
740
    // pathname.  This is a bit messy since we have to deal with mount
741
    // names of both "/" and "/foo" and pathnames that start with '/'
742
    // or are empty.
743
    if( *(bp-1) != '/' && *p != '\0' ) *bp++ = '/';
744
    if( *p == '/' ) p++;
745
 
746
    // Now copy the path over.
747
    while( *p )
748
        *bp++ = *p++;
749
 
750
    *bp = '\0';                         // Terminate the string
751
 
752
    // All done!
753
 
754
#endif
755
 
756
    FILEIO_RETURN_VALUE(buf);
757
}
758
 
759
// -------------------------------------------------------------------------
760
// EOF file.cxx

powered by: WebSVN 2.1.0

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