unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / src / dir.cxx
1 //==========================================================================
2 //
3 //      dir.cxx
4 //
5 //      Fileio directory support
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 //####ECOSGPLCOPYRIGHTEND####
37 //==========================================================================
38 //#####DESCRIPTIONBEGIN####
39 //
40 // Author(s):           nickg
41 // Contributors:        nickg
42 // Date:                2000-05-25
43 // Purpose:             Fileio directory support
44 // Description:         Support for directory operations.
45 //                      
46 //              
47 //              
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/hal.h>
54 #include <pkgconf/io_fileio.h>
55
56 #include <cyg/infra/cyg_trac.h>        // tracing macros
57 #include <cyg/infra/cyg_ass.h>         // assertion macros
58
59 #include <stdarg.h>                     // for fcntl()
60
61 #include "fio.h"                       // Private header
62
63 #include <dirent.h>                    // struct dirent
64
65 //==========================================================================
66
67 #define DIROPEN_RETURN_ERR( err )               \
68 CYG_MACRO_START                                 \
69     errno = err;                                \
70     CYG_REPORT_RETVAL( NULL );                  \
71     return NULL;                                \
72 CYG_MACRO_END
73
74 //==========================================================================
75 // Implement filesystem locking protocol. 
76
77 #define LOCK_FS( _mte_ )  {                             \
78    CYG_ASSERT(_mte_ != NULL, "Bad mount table entry");  \
79    cyg_fs_lock( _mte_, (_mte_)->fs->syncmode);          \
80 }
81
82 #define UNLOCK_FS( _mte_ ) cyg_fs_unlock( _mte_, (_mte_)->fs->syncmode)
83
84 //==========================================================================
85 // Open a directory for reading
86
87 extern DIR *opendir( const char *dirname )
88 {
89     FILEIO_ENTRY();
90
91     CYG_CANCELLATION_POINT;
92
93     int ret = 0;
94     int fd;
95     cyg_file *file;
96     cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
97     cyg_dir dir = cyg_cdir_dir;
98     const char *name = dirname;
99
100     fd = cyg_fd_alloc(1); // Never return fd 0
101
102     if( fd < 0 )
103         DIROPEN_RETURN_ERR(EMFILE);
104     
105     file = cyg_file_alloc();
106
107     if( file == NULL )
108     {
109         cyg_fd_free(fd);
110         DIROPEN_RETURN_ERR(ENFILE);
111     }
112     
113     ret = cyg_mtab_lookup( &dir, &name, &mte );
114     
115     if( 0 != ret )
116     {
117         cyg_fd_free(fd);
118         cyg_file_free(file);
119         DIROPEN_RETURN_ERR(ENOENT);
120     }
121
122     LOCK_FS( mte );
123     
124     ret = mte->fs->opendir( mte, dir, name, file );
125     
126     UNLOCK_FS( mte );
127     
128     if( 0 != ret )
129     {
130         cyg_fd_free(fd);
131         cyg_file_free(file);
132         DIROPEN_RETURN_ERR(ret);
133     }
134
135     file->f_flag |= CYG_FDIR|CYG_FREAD;
136     file->f_mte = mte;
137     file->f_syncmode = mte->fs->syncmode;
138     
139     cyg_fd_assign( fd, file );
140
141     DIR *dirp = (DIR *)fd;
142     
143     FILEIO_RETURN_VALUE(dirp);
144 }
145
146 //==========================================================================
147 // Read a directory entry.
148 // This is the thread-unsafe version that uses a static result buffer.
149 // It just calls the thread-safe version to do the work.
150
151 extern struct dirent *readdir( DIR *dirp )
152 {
153     FILEIO_ENTRY();
154     
155     static struct dirent ent;
156     struct dirent *result;
157     int err;
158
159     err = readdir_r( dirp, &ent, &result );
160
161     if( err != 0 )
162     {
163         errno = err;
164         FILEIO_RETURN_VALUE( NULL );
165     }
166     
167     FILEIO_RETURN_VALUE( result );
168 }
169
170 //==========================================================================
171
172 extern int readdir_r( DIR *dirp, struct dirent *entry, struct dirent **result )
173 {
174     FILEIO_ENTRY();
175
176     int fd = (int)dirp;    
177     ssize_t res;
178
179     *result = NULL;
180
181     if( NULL == dirp )
182     {
183         FILEIO_RETURN_VALUE( EBADF );
184     }
185
186 #ifdef CYGPKG_FILEIO_DIRENT_DTYPE
187     // d_type is only supposed by a few filesystems, so make sure other
188     // filesystems return a sane value;
189     entry->d_type = 0;
190 #endif
191
192     res = read( fd, (void *)entry, sizeof(struct dirent));
193
194     if( res < 0 )
195     {
196         FILEIO_RETURN_VALUE( errno );
197     }
198     
199     if( res > 0 )
200         *result = entry;
201
202 #ifdef CYGPKG_FILEIO_DIRENT_DTYPE
203     // Only the lower bits contain the type of file, so and those out.
204     entry->d_type &= S_IFMT;
205 #endif
206     
207
208     FILEIO_RETURN( ENOERR );
209 }
210
211 //==========================================================================
212
213 extern void rewinddir( DIR *dirp )
214 {
215     FILEIO_ENTRY();
216
217     int fd = (int)dirp;
218
219     lseek( fd, 0, SEEK_SET );
220     
221     FILEIO_RETURN_VOID();
222 }
223
224 //==========================================================================
225
226 extern int closedir( DIR *dirp )
227 {
228     FILEIO_ENTRY();
229
230     int fd = (int)dirp;
231     int err = close( fd );
232
233     FILEIO_RETURN_VALUE( err );
234 }
235
236 // -------------------------------------------------------------------------
237 // EOF dir.cxx