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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [fileio/] [current/] [src/] [file.cxx] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):           nickg
43
// Contributors:        nickg
44
// Contributors:        rutger at cs dot vu dot nl: chmod()
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_ASSERT(_mte_->fs != NULL, "Bad mount filesystem entry");  \
75
   cyg_fs_lock( _mte_, (_mte_)->fs->syncmode);          \
76
}
77
 
78
#define UNLOCK_FS( _mte_ ) cyg_fs_unlock( _mte_, (_mte_)->fs->syncmode)
79
 
80
//==========================================================================
81
// A local strcpy clone that returns a pointer to the end of the copied
82
// string, not the beginning.
83
 
84
static char *my_strcpy( char *s1, const char *s2 )
85
{
86
    while( (*s1++ = *s2++) != 0);
87
    return s1-1;
88
}
89
 
90
//==========================================================================
91
// Compare a pathname fragment with an element in a pathname. This
92
// deals with zero or separator termination and avoids substring
93
// matches.
94
 
95
static int pathcmp( const char *path, const char *name )
96
{
97
    while( *path == *name && *path != '\0' )
98
        path++, name++;
99
    if( *name != '\0' ) return false;
100
    if( *path == '/' || *path == '\0' ) return true;
101
    return false;
102
}
103
 
104
//==========================================================================
105
// CWD support
106
 
107
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
108
 
109
// buffer for storing CWD path
110
static char cwd[PATH_MAX];
111
static size_t cwd_size = 0;
112
 
113
 
114
static void update_cwd( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
115
{
116
    char *p = cwd;
117
 
118
    if( mte != cyg_cdir_mtab_entry || dir != cyg_cdir_dir )
119
    {
120
        // Here, the path is relative to the root of the filesystem,
121
        // or in a totally new filesystem, initialize the cwd with the
122
        // mount point name of the filesystem.
123
 
124
        p = my_strcpy( p, mte->name );
125
    }
126
    else p = cwd+cwd_size;
127
 
128
    // We must now copy the path into the cwd buffer while dealing
129
    // with any "." and ".."  components textually.
130
 
131
    while( *path != '\0' )
132
    {
133
        // skip any stray directory separators.
134
        if( *path == '/' ) path++;
135
 
136
        // Look for a "." entry and just ignore it.
137
        if( pathcmp( path, "." ) )
138
        {
139
            path++;
140
            continue;
141
        }
142
 
143
        // Look for a ".." entry. If found, chew off the last cwd
144
        // entry.
145
        if( pathcmp( path, ".." ) )
146
        {
147
            while( *(--p) != '/' );     // back up to last '/'
148
            path += 2;                  // skip "..".
149
            continue;
150
        }
151
 
152
        // Otherwise just copy the name fragment over to the cwd.
153
 
154
        if( *(p-1) != '/' )
155
            *p++ = '/';        // add a directory separator
156
        while( *path != '/' && *path != '\0' )
157
            *p++ = *path++;
158
 
159
    }
160
 
161
    // Zero terminate the cwd.
162
    *p = '\0';
163
 
164
    // update size
165
    cwd_size = p-cwd;
166
}
167
 
168
#else
169
 
170
#ifdef CYGPKG_KERNEL
171
static Cyg_Mutex getcwd_lock CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
172
#endif
173
 
174
#endif
175
 
176
 
177
//==========================================================================
178
// Open a file
179
 
180
__externC int open( const char *path, int oflag, ... )
181
{
182
    FILEIO_ENTRY();
183
 
184
    // we want to be sure we pull in stdin/out/err, so they can be
185
    // assigned to fds 0, 1 and 2
186
#ifdef CYGINT_ISO_STDIO_STREAMS
187
    CYG_REFERENCE_OBJECT(stdin);
188
    CYG_REFERENCE_OBJECT(stdout);
189
    CYG_REFERENCE_OBJECT(stderr);
190
#endif
191
 
192
    CYG_CANCELLATION_POINT;
193
 
194
    int ret = 0;
195
    int fd;
196
    cyg_file *file;
197
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
198
    cyg_dir dir = cyg_cdir_dir;
199
    const char *name = path;
200
 
201
    // At least one of O_RDONLY, O_WRONLY, O_RDWR must be provided
202
    if( (oflag & O_RDWR) == 0 )
203
        FILEIO_RETURN(EINVAL);
204
 
205
    fd = cyg_fd_alloc(0);
206
 
207
    if( fd < 0 )
208
        FILEIO_RETURN(EMFILE);
209
 
210
    file = cyg_file_alloc();
211
 
212
    if( file == NULL )
213
    {
214
        cyg_fd_free(fd);
215
        FILEIO_RETURN(ENFILE);
216
    }
217
 
218
    ret = cyg_mtab_lookup( &dir, &name, &mte );
219
 
220
    if( 0 != ret )
221
    {
222
        cyg_fd_free(fd);
223
        cyg_file_free(file);
224
        FILEIO_RETURN(ENOENT);
225
    }
226
 
227
    LOCK_FS( mte );
228
 
229
    ret = mte->fs->open( mte, dir, name, oflag, file );
230
 
231
    UNLOCK_FS( mte );
232
 
233
    if( 0 != ret )
234
    {
235
        cyg_fd_free(fd);
236
        cyg_file_free(file);
237
        FILEIO_RETURN(ret);
238
    }
239
 
240
    file->f_mte = mte;
241
    file->f_syncmode = mte->fs->syncmode;
242
 
243
    cyg_fd_assign( fd, file );
244
 
245
    FILEIO_RETURN_VALUE(fd);
246
}
247
 
248
//==========================================================================
249
// create a file
250
 
251
__externC int creat( const char *path, mode_t mode )
252
{
253
    return open( path, O_WRONLY | O_CREAT | O_TRUNC, mode );
254
}
255
 
256
 
257
//==========================================================================
258
// Unlink/remove a file
259
 
260
__externC int unlink( const char *path )
261
{
262
    FILEIO_ENTRY();
263
 
264
    int ret = 0;
265
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
266
    cyg_dir dir = cyg_cdir_dir;
267
    const char *name = path;
268
 
269
    ret = cyg_mtab_lookup( &dir, &name, &mte );
270
 
271
    if( 0 != ret )
272
        FILEIO_RETURN(ENOENT);
273
 
274
    LOCK_FS( mte );
275
 
276
    ret = mte->fs->unlink( mte, dir, name );
277
 
278
    UNLOCK_FS( mte );
279
 
280
    FILEIO_RETURN(ret);
281
}
282
 
283
//==========================================================================
284
// Make a directory
285
 
286
__externC int mkdir( const char *path, mode_t mode )
287
{
288
    FILEIO_ENTRY();
289
 
290
    int ret = 0;
291
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
292
    cyg_dir dir = cyg_cdir_dir;
293
    const char *name = path;
294
 
295
    mode=mode;
296
 
297
    ret = cyg_mtab_lookup( &dir, &name, &mte );
298
 
299
    if( 0 != ret )
300
        FILEIO_RETURN(ENOENT);
301
 
302
    LOCK_FS( mte );
303
 
304
    ret = mte->fs->mkdir( mte, dir, name );
305
 
306
    UNLOCK_FS( mte );
307
 
308
    FILEIO_RETURN(ret);
309
}
310
 
311
//==========================================================================
312
// Remove a directory
313
 
314
__externC int rmdir( const char *path )
315
{
316
    FILEIO_ENTRY();
317
 
318
    int ret = 0;
319
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
320
    cyg_dir dir = cyg_cdir_dir;
321
    const char *name = path;
322
 
323
    ret = cyg_mtab_lookup( &dir, &name, &mte );
324
 
325
    if( 0 != ret )
326
        FILEIO_RETURN(ENOENT);
327
 
328
    LOCK_FS( mte );
329
 
330
    ret = mte->fs->rmdir( mte, dir, name );
331
 
332
    UNLOCK_FS( mte );
333
 
334
    FILEIO_RETURN(ret);
335
}
336
 
337
//==========================================================================
338
// Rename a file
339
 
340
__externC int rename( const char *path1, const char *path2 ) __THROW
341
{
342
    FILEIO_ENTRY();
343
 
344
    int ret = 0;
345
    cyg_mtab_entry *mte1 = cyg_cdir_mtab_entry;
346
    cyg_mtab_entry *mte2 = cyg_cdir_mtab_entry;
347
    cyg_dir dir1 = cyg_cdir_dir;
348
    cyg_dir dir2 = cyg_cdir_dir;
349
    const char *name1 = path1;
350
    const char *name2 = path2;
351
 
352
    ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
353
 
354
    if( 0 != ret )
355
        FILEIO_RETURN(ENOENT);
356
 
357
    ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
358
 
359
    if( 0 != ret )
360
        FILEIO_RETURN(ENOENT);
361
 
362
    // Cannot rename between different filesystems
363
    if( mte1 != mte2 )
364
        FILEIO_RETURN(EXDEV);
365
 
366
    LOCK_FS( mte1 );
367
 
368
    ret = mte1->fs->rename( mte1, dir1, name1, dir2, name2 );
369
 
370
    UNLOCK_FS( mte1 );
371
 
372
    FILEIO_RETURN(ret);
373
}
374
 
375
//==========================================================================
376
// Create a link from an existing file (path1) to a new one (path2)
377
 
378
__externC int link( const char *path1, const char *path2 )
379
{
380
    FILEIO_ENTRY();
381
 
382
    int ret = 0;
383
    cyg_mtab_entry *mte1 = cyg_cdir_mtab_entry;
384
    cyg_mtab_entry *mte2 = cyg_cdir_mtab_entry;
385
    cyg_dir dir1 = cyg_cdir_dir;
386
    cyg_dir dir2 = cyg_cdir_dir;
387
    const char *name1 = path1;
388
    const char *name2 = path2;
389
 
390
    ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
391
 
392
    if( 0 != ret )
393
        FILEIO_RETURN(ENOENT);
394
 
395
    ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
396
 
397
    if( 0 != ret )
398
        FILEIO_RETURN(ENOENT);
399
 
400
    // Cannot hard-link between different filesystems
401
    if( mte1 != mte2 )
402
        FILEIO_RETURN(EXDEV);
403
 
404
    LOCK_FS( mte1 );
405
 
406
    ret = mte1->fs->link( mte1, dir1, name1, dir2, name2, CYG_FSLINK_HARD );
407
 
408
    UNLOCK_FS( mte1 );
409
 
410
    FILEIO_RETURN(ret);
411
}
412
 
413
//==========================================================================
414
// Change current directory
415
 
416
__externC int chdir( const char *path )
417
{
418
    FILEIO_ENTRY();
419
 
420
    int ret = 0;
421
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
422
    cyg_dir dir = cyg_cdir_dir;
423
    cyg_dir newdir;
424
    const char *name = path;
425
 
426
    ret = cyg_mtab_lookup( &dir, &name, &mte );
427
 
428
    if( 0 != ret )
429
        FILEIO_RETURN(ENOENT);
430
 
431
    LOCK_FS(mte);
432
 
433
    ret = mte->fs->chdir( mte, dir, name, &newdir );
434
 
435
    UNLOCK_FS(mte);
436
 
437
    if( 0 != ret )
438
        FILEIO_RETURN(ret);
439
 
440
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
441
    update_cwd( mte, dir, name );
442
#endif
443
 
444
    if( cyg_cdir_mtab_entry != NULL && cyg_cdir_dir != CYG_DIR_NULL )
445
    {
446
        // Now detach from current cyg_cdir. We call the current directory's
447
        // chdir routine with a NULL dir_out pointer.
448
 
449
        LOCK_FS(cyg_cdir_mtab_entry);
450
 
451
        ret = cyg_cdir_mtab_entry->fs->chdir( cyg_cdir_mtab_entry, cyg_cdir_dir, NULL, NULL );
452
 
453
        UNLOCK_FS(cyg_cdir_mtab_entry);
454
 
455
        // We really shouldn't get an error here.
456
        if( 0 != ret )
457
            FILEIO_RETURN(ret);
458
    }
459
 
460
    cyg_cdir_mtab_entry = mte;
461
    cyg_cdir_dir = newdir;
462
 
463
    FILEIO_RETURN(ENOERR);
464
}
465
 
466
//==========================================================================
467
// Get file statistics
468
 
469
__externC int stat( const char *path, struct stat *buf )
470
{
471
    FILEIO_ENTRY();
472
 
473
    int ret = 0;
474
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
475
    cyg_dir dir = cyg_cdir_dir;
476
    const char *name = path;
477
 
478
    ret = cyg_mtab_lookup( &dir, &name, &mte );
479
 
480
    if( 0 != ret )
481
        FILEIO_RETURN(ENOENT);
482
 
483
    LOCK_FS( mte );
484
 
485
    ret = mte->fs->stat( mte, dir, name, buf );
486
 
487
    UNLOCK_FS( mte );
488
 
489
    FILEIO_RETURN(ret);
490
}
491
 
492
//==========================================================================
493
// Get file configurable pathname variables
494
 
495
__externC long pathconf( const char *path, int vname )
496
{
497
    FILEIO_ENTRY();
498
 
499
    int ret = 0;
500
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
501
    cyg_dir dir = cyg_cdir_dir;
502
    const char *name = path;
503
 
504
    ret = cyg_mtab_lookup( &dir, &name, &mte );
505
 
506
    if( 0 != ret )
507
        FILEIO_RETURN(ENOENT);
508
 
509
    struct cyg_pathconf_info info;
510
 
511
    info.name = vname;
512
    info.value = 0;
513
 
514
    LOCK_FS( mte );
515
 
516
    ret = mte->fs->getinfo( mte, dir, name,
517
                            FS_INFO_CONF, (char *)&info, sizeof(info) );
518
 
519
    UNLOCK_FS( mte );
520
 
521
    if( 0 != ret )
522
        FILEIO_RETURN(ret);
523
 
524
    FILEIO_RETURN_VALUE(info.value);
525
}
526
 
527
//==========================================================================
528
// Sync filesystem without unmounting
529
 
530
__externC int cyg_fs_fssync( const char *path )
531
{
532
    FILEIO_ENTRY();
533
 
534
    int ret = 0;
535
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
536
    cyg_dir dir = cyg_cdir_dir;
537
    const char *name = path;
538
 
539
    ret = cyg_mtab_lookup( &dir, &name, &mte );
540
 
541
    if( 0 != ret )
542
        FILEIO_RETURN(ENOENT);
543
 
544
    LOCK_FS( mte );
545
 
546
    ret = mte->fs->setinfo( mte, dir, name, FS_INFO_SYNC, NULL, 0 );
547
 
548
    UNLOCK_FS( mte );
549
 
550
    if( 0 != ret )
551
        FILEIO_RETURN(ret);
552
 
553
    FILEIO_RETURN_VALUE(ENOERR);
554
}
555
 
556
//==========================================================================
557
// Set file attributes
558
 
559
__externC int cyg_fs_set_attrib( const char *fname,
560
                                 const cyg_fs_attrib_t new_attrib )
561
{
562
    FILEIO_ENTRY();
563
 
564
    int ret = 0;
565
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
566
    cyg_dir dir = cyg_cdir_dir;
567
    const char *name = fname;
568
 
569
    ret = cyg_mtab_lookup( &dir, &name, &mte );
570
 
571
    if( 0 != ret )
572
        FILEIO_RETURN(ENOENT);
573
 
574
    LOCK_FS( mte );
575
 
576
    ret = mte->fs->setinfo( mte, dir, name,
577
                            FS_INFO_ATTRIB,
578
                            (char *)&new_attrib, sizeof(new_attrib) );
579
 
580
    UNLOCK_FS( mte );
581
 
582
    if( 0 != ret )
583
        FILEIO_RETURN(ret);
584
 
585
    FILEIO_RETURN(ENOERR);
586
}
587
 
588
//==========================================================================
589
// Get file attributes
590
 
591
__externC int cyg_fs_get_attrib( const char *fname,
592
                                 cyg_fs_attrib_t * const file_attrib )
593
{
594
    FILEIO_ENTRY();
595
 
596
    int ret = 0;
597
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
598
    cyg_dir dir = cyg_cdir_dir;
599
    const char *name = fname;
600
 
601
    ret = cyg_mtab_lookup( &dir, &name, &mte );
602
 
603
    if( 0 != ret )
604
        FILEIO_RETURN(ENOENT);
605
 
606
    LOCK_FS( mte );
607
 
608
    ret = mte->fs->getinfo( mte, dir, name,
609
                            FS_INFO_ATTRIB,
610
                            (char *)file_attrib, sizeof(*file_attrib) );
611
 
612
    UNLOCK_FS( mte );
613
 
614
    if( 0 != ret )
615
        FILEIO_RETURN(ret);
616
 
617
    FILEIO_RETURN(ENOERR);
618
}
619
 
620
//==========================================================================
621
// Access() function.
622
// This simply piggybacks onto stat().
623
 
624
extern int      access(const char *path, int amode)
625
{
626
    FILEIO_ENTRY();
627
 
628
    int ret;
629
    struct stat buf;
630
 
631
    ret = stat( path, &buf );
632
 
633
    // Translate not found into EACCES if the F_OK bit is
634
    // set.
635
    if( (amode & F_OK) && (ret < 0) && (errno == ENOENT) )
636
        FILEIO_RETURN(EACCES);
637
 
638
    // All other errors go straight back to the user.
639
    if( ret < 0 )
640
        FILEIO_RETURN_VALUE(ret);
641
 
642
    // At present we do not have any access modes, so there is nothing
643
    // to test.  Just return success for all access modes.
644
 
645
    FILEIO_RETURN(ENOERR);
646
}
647
 
648
//==========================================================================
649
// getcwd()
650
 
651
__externC char *getcwd( char *buf, size_t size )
652
{
653
    FILEIO_ENTRY();
654
 
655
    int err = ENOERR;
656
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
657
    cyg_dir dir = cyg_cdir_dir;
658
    cyg_getcwd_info info;
659
 
660
    if( size == 0 )
661
    {
662
        errno = EINVAL;
663
        FILEIO_RETURN_VALUE(NULL);
664
    }
665
 
666
    info.buf = buf;
667
    info.size = size;
668
 
669
    LOCK_FS( mte );
670
 
671
    err = mte->fs->getinfo( mte, dir, "",
672
                            FS_INFO_GETCWD, (char *)&info, sizeof(info) );
673
 
674
    UNLOCK_FS( mte );
675
 
676
    if( err == ENOERR )
677
        FILEIO_RETURN_VALUE(buf);
678
 
679
    // Attempting to use filesystem support for getcwd() has
680
    // failed.
681
 
682
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
683
 
684
    // If this option is set, the current directory path has been
685
    // tracked in chdir(). Just report that value here.
686
 
687
    if( size < cwd_size+1 )
688
    {
689
        errno = ERANGE;
690
        FILEIO_RETURN_VALUE(NULL);
691
    }
692
 
693
    char *p = my_strcpy( buf, cwd );
694
    *p = '\0';
695
 
696
#else
697
 
698
    // As a fallback we try to use ".." entries in the directory tree
699
    // to climb back up to the root.  Because we cannot assume that
700
    // any filesystem can handle more than one directory pointer we
701
    // have to do the climbing textually, by manufacturing a path name
702
    // consisting of ".."s. At each level we then scan the parent
703
    // directory looking for the entry for the lower level directory
704
    // by matching st_ino values. This is not guaranteed to work at
705
    // all since there is no requirement on filesystems to support "."
706
    // and "..", or for them to report distinct inode values in
707
    // stat().
708
 
709
    static char ddbuf[PATH_MAX];
710
    char *p = buf+size-1;
711
    int ddbufpos;
712
 
713
    // Claim lock to serialize use of ddbuf.
714
    FILEIO_MUTEX_LOCK(getcwd_lock);
715
 
716
    // Initialize ddbuf with ".".
717
    ddbuf[0] = '.';
718
    ddbuf[1] = '\0';
719
    ddbufpos = 1;
720
 
721
    // Start result buffer with a zero terminator. We accumulate the
722
    // path name in the top end of the result buffer.
723
    *p = '\0';
724
 
725
    for(;;)
726
    {
727
        struct stat sdbuf;
728
        struct stat sddbuf;
729
 
730
        // Get status for "." and "..". If the filesystem does not
731
        // support these, then this whole function will fail here.
732
 
733
        err = stat( ddbuf, &sdbuf );
734
        if( err < 0 ) break;
735
 
736
        ddbuf[ddbufpos++] = '/';
737
        ddbuf[ddbufpos++] = '.';
738
        ddbuf[ddbufpos++] = '.';
739
        ddbuf[ddbufpos] = '\0';
740
 
741
        err = stat( ddbuf, &sddbuf );
742
        if( err < 0 ) break;
743
 
744
        // See whether we are at the root. This will be true when
745
        // the inode numbers of "." and ".." are the same.
746
        if( sdbuf.st_ino == sddbuf.st_ino )
747
            break;
748
 
749
        // We now need to find an entry in the ".." directory that
750
        // matches the inode number of ".".
751
 
752
        struct dirent de;
753
        DIR *d = opendir( ddbuf );
754
        if( d == NULL )
755
        {
756
            err = -1;
757
            break;
758
        }
759
 
760
        for(;;)
761
        {
762
            struct dirent *res;
763
            struct stat objstat;
764
            int i;
765
 
766
            err = readdir_r( d, &de, &res );
767
            if( err < 0 || res == NULL ) break;
768
 
769
            // Skip "." and ".." entries.
770
            if( pathcmp( de.d_name, "." ) || pathcmp( de.d_name, ".." ) )
771
                continue;
772
 
773
            // Tack the name of the directory entry on to the ddbuf
774
            // and stat the object.
775
 
776
            ddbuf[ddbufpos] = '/';
777
            for( i = 0; de.d_name[i] != '\0'; i++ )
778
                ddbuf[ddbufpos+i+1] = de.d_name[i];
779
            ddbuf[ddbufpos+i+1] = '\0';
780
 
781
            // Take a look at it
782
            err = stat( ddbuf, &objstat );
783
            if( err < 0 ) break;
784
 
785
            // Cast out directories
786
            if( !S_ISDIR(objstat.st_mode) )
787
                continue;
788
 
789
            // We have a directory. Compare its inode with that of "."
790
            // and if they are the same, we have found our entry.
791
 
792
            if( sdbuf.st_ino == objstat.st_ino )
793
                break;
794
        }
795
 
796
        ddbuf[ddbufpos] = '\0'; // reterminate ddbuf
797
 
798
        closedir( d );
799
 
800
        // Halt on any errors.
801
        if( err < 0 )
802
            break;
803
 
804
        // Here de contains the name of the directory entry in ".."
805
        // that has the same inode as ".". Add the name to the path we
806
        // are accumulating in the buffer.
807
 
808
        char *q = de.d_name;
809
        while( *q != '\0' ) q++;        // skip to end of name
810
 
811
        do
812
        {
813
            *--p = *--q;
814
        } while( q != de.d_name );
815
 
816
        *--p = '/';                     // add a separator
817
    }
818
 
819
    // We have finished using ddbuf now.
820
    FILEIO_MUTEX_UNLOCK(getcwd_lock);
821
 
822
    if( err < 0 )
823
        FILEIO_RETURN_VALUE(NULL);
824
 
825
    // We have the directory path in the top end of the buffer.  Add
826
    // the mount point name at the beginning and copy the rest of the
827
    // name down.
828
 
829
    char *bp = buf;
830
 
831
    bp = my_strcpy( bp, mte->name );
832
 
833
    // Sort out the separators between the mount name and the
834
    // pathname.  This is a bit messy since we have to deal with mount
835
    // names of both "/" and "/foo" and pathnames that start with '/'
836
    // or are empty.
837
    if( *(bp-1) != '/' && *p != '\0' ) *bp++ = '/';
838
    if( *p == '/' ) p++;
839
 
840
    // Now copy the path over.
841
    while( *p )
842
        *bp++ = *p++;
843
 
844
    *bp = '\0';                         // Terminate the string
845
 
846
    // All done!
847
 
848
#endif
849
 
850
    FILEIO_RETURN_VALUE(buf);
851
}
852
 
853
//==========================================================================
854
// FS get info.
855
 
856
__externC int cyg_fs_getinfo( const char *path, int key, void *buf, int len )
857
{
858
    FILEIO_ENTRY();
859
 
860
    int ret = 0;
861
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
862
    cyg_dir dir = cyg_cdir_dir;
863
    const char *name = path;
864
 
865
    ret = cyg_mtab_lookup( &dir, &name, &mte );
866
 
867
    if( 0 != ret )
868
        FILEIO_RETURN(ENOENT);
869
 
870
    LOCK_FS( mte );
871
 
872
    ret = mte->fs->getinfo( mte, dir, name, key, buf, len );
873
 
874
    UNLOCK_FS( mte );
875
 
876
    FILEIO_RETURN(ret);
877
}
878
 
879
//==========================================================================
880
// FS set info.
881
 
882
__externC int cyg_fs_setinfo( const char *path, int key, void *buf, int len )
883
{
884
    FILEIO_ENTRY();
885
 
886
    int ret = 0;
887
    cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
888
    cyg_dir dir = cyg_cdir_dir;
889
    const char *name = path;
890
 
891
    ret = cyg_mtab_lookup( &dir, &name, &mte );
892
 
893
    if( 0 != ret )
894
        FILEIO_RETURN(ENOENT);
895
 
896
    LOCK_FS( mte );
897
 
898
    ret = mte->fs->setinfo( mte, dir, name, key, buf, len );
899
 
900
    UNLOCK_FS( mte );
901
 
902
    FILEIO_RETURN(ret);
903
}
904
 
905
//==========================================================================
906
// chmod
907
 
908
__externC int chmod(const char *path, mode_t mode)
909
{
910
    int ret;
911
 
912
    FILEIO_ENTRY();
913
 
914
    ret = cyg_fs_setinfo(path, FS_INFO_CHMOD, &mode, sizeof(mode));
915
 
916
    FILEIO_RETURN(ret);
917
}
918
 
919
// -------------------------------------------------------------------------
920
// EOF file.cxx

powered by: WebSVN 2.1.0

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