source: rtems/c/src/lib/libc/imfs_directory.c @ c0438add

4.104.114.84.95
Last change on this file since c0438add was 07a3253d, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/98 at 19:07:58

Added base version of file system infrastructure. This includes a major
overhaul of the RTEMS system call interface. This base file system is
the "In-Memory File System" aka IMFS.

The design and implementation was done by the following people:

+ Joel Sherrill (joel@…)
+ Jennifer Averett (jennifer@…)
+ Steve "Mr Mount" Salitasc (salitasc@…)
+ Kerwin Wade (wade@…)

PROBLEMS
========

+ It is VERY likely that merging this will break the UNIX port. This

can/will be fixed.

+ There is likely some reentrancy/mutual exclusion needed.

+ Eventually, there should be a "mini-IMFS" description table to

eliminate links, symlinks, etc to save memory. All you need to
have "classic RTEMS" functionality is technically directories
and device IO. All the rest could be left out to save memory.

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 *  XXX
3 *
4 *  COPYRIGHT (c) 1989-1998.
5 *  On-Line Applications Research Corporation (OAR).
6 *  Copyright assigned to U.S. Government, 1994.
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.OARcorp.com/rtems/license.html.
11 *
12 *  $Id$
13 */
14
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <chain.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <assert.h>
24#include <dirent.h>
25
26#include "imfs.h"
27#include "libio_.h"
28
29long getdents(
30  int dd_fd,
31  char *dd_buf,
32  int dd_len
33);
34
35/* -----------------------------------------------------------------------
36 * This rountine will verify that the node being opened as a directory is
37 * in fact a directory node. If it is then the offset into the directory
38 * will be set to 0 to position to the first directory entry.
39 */
40
41int imfs_dir_open(
42  rtems_libio_t  *iop,
43  const char *pathname,
44  unsigned32 flag,
45  unsigned32 mode
46)
47{
48  IMFS_jnode_t      *the_jnode;
49
50  /* Is the node a directory ? */
51  the_jnode = (IMFS_jnode_t *) iop->file_info;
52
53  if ( the_jnode->type != IMFS_DIRECTORY )
54     return -1;         /* It wasn't a directory --> return error */
55
56  iop->offset = 0;
57  return 0;
58}
59
60
61
62/* -----------------------------------------------------------------------
63 * This routine will read the next directory entry based on the directory
64 * offset. The offset should be equal to -n- time the size of an individual
65 * dirent structure. If n is not an integer multiple of the sizeof a
66 * dirent structure, an integer division will be performed to determine
67 * directory entry that will be returned in the buffer. Count should reflect
68 * -m- times the sizeof dirent bytes to be placed in the buffer.
69 * If there are not -m- dirent elements from the current directory position
70 * to the end of the exisiting file, the remaining entries will be placed in
71 * the buffer and the returned value will be equal to -m actual- times the
72 * size of a directory entry.
73 */
74
75int imfs_dir_read(
76  rtems_libio_t  *iop,
77  void *buffer,
78  unsigned32 count
79)
80{
81  /*
82   *  Read up to element  iop->offset in the directory chain of the
83   *  imfs_jnode_t struct for this file descriptor.
84   */
85   Chain_Node        *the_node;
86   Chain_Control     *the_chain;
87   IMFS_jnode_t      *the_jnode;
88   int                bytes_transferred;
89   int                current_entry;
90   int                first_entry;
91   int                last_entry;
92   struct dirent      tmp_dirent;
93
94   the_jnode = (IMFS_jnode_t *)iop->file_info;
95   the_chain = &the_jnode->info.directory.Entries;
96   
97   if ( Chain_Is_empty( the_chain ) )
98      return 0;
99
100   /* Move to the first of the desired directory entries */
101   the_node = the_chain->first;
102
103   bytes_transferred = 0;
104   first_entry = iop->offset;
105   /* protect against using sizes that are not exact multiples of the */
106   /* -dirent- size. These could result in unexpected results          */
107   last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
108
109   /* The directory was not empty so try to move to the desired entry in chain*/
110   for(
111      current_entry = 0;
112      current_entry < last_entry;
113      current_entry = current_entry + sizeof(struct dirent) ){
114
115      if ( Chain_Is_tail( the_chain, the_node ) ){
116         /* We hit the tail of the chain while trying to move to the first */
117         /* entry in the read */
118         return bytes_transferred;  /* Indicate that there are no more */
119                                    /* entries to return */
120      }
121   
122      if( current_entry >= first_entry ) {
123         /* Move the entry to the return buffer */
124         tmp_dirent.d_ino = 1;
125         tmp_dirent.d_off = current_entry;
126         tmp_dirent.d_reclen = sizeof( struct dirent );
127         the_jnode = (IMFS_jnode_t *) the_node;
128         tmp_dirent.d_namlen = strlen( the_jnode->name );
129         sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
130         memcpy(
131            buffer + bytes_transferred,
132            (void *)&tmp_dirent,
133            sizeof( struct dirent )
134         );
135         iop->offset = iop->offset + sizeof(struct dirent);
136         bytes_transferred = bytes_transferred + sizeof( struct dirent );
137      }
138
139      the_node = the_node->next;
140   }
141
142   /* Success */
143   return bytes_transferred;
144}
145
146
147
148/* -----------------------------------------------------------------------
149 * This routine will be called by the generic close routine to cleanup any
150 * resources that have been allocated for the management of the file
151 */
152
153int imfs_dir_close(
154  rtems_libio_t  *iop
155)
156{
157  /* The generic close routine handles the deallocation of the file control */
158  /* and associated memory. At present the imfs_dir_close simply      */
159  /* returns a successful completion status                                 */
160 
161  return 0;
162}
163
164
165
166/* -----------------------------------------------------------------------
167 * This routine will behave in one of three ways based on the state of
168 * argument whence. Based on the state of its value the offset argument will
169 * be interpreted using one of the following methods:
170 *
171 *      SEEK_SET - offset is the absolute byte offset from the start of the
172 *                 logical start of the dirent sequence that represents the
173 *                 directory
174 *      SEEK_CUR - offset is used as the relative byte offset from the current
175 *                 directory position index held in the iop structure
176 *      SEEK_END - N/A --> This will cause an assert.
177 */
178
179int imfs_dir_lseek(
180  rtems_libio_t  *iop,
181  off_t           offset,
182  int             whence
183)
184{
185  off_t normal_offset;
186
187  normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
188
189
190  switch( whence )
191  {
192     case SEEK_SET:     /* absolute move from the start of the file */
193        iop->offset = normal_offset;
194        break;
195
196     case SEEK_CUR:     /* relative move */
197        iop->offset = iop->offset + normal_offset;
198        break;
199
200     case SEEK_END:     /* Movement past the end of the directory via lseek */
201                        /* is not a permitted operation                     */
202      default:
203        set_errno_and_return_minus_one( EINVAL );
204        break;
205
206  }
207
208  return 0;
209}
210
211
212
213/* -----------------------------------------------------------------------
214 * This routine will obtain the following information concerning the current
215 * directory:
216 *      st_dev          0ll
217 *      st_ino          1
218 *      st_mode         mode extracted from the jnode
219 *      st_nlink        number of links to this node
220 *      st_uid          uid extracted from the jnode
221 *      st_gid          gid extracted from the jnode
222 *      st_rdev         0ll
223 *      st_size         the number of bytes in the directory
224 *                      This is calculated by taking the number of entries
225 *                      in the directory and multiplying by the size of a
226 *                      dirent structure
227 *      st_blksize      0
228 *      st_blocks       0
229 *      st_atime        time of last access
230 *      st_mtime        time of last modification
231 *      st_ctime        time of the last change
232 *
233 * This information will be returned to the calling function in a -stat- struct
234 *     
235 */
236
237int imfs_dir_fstat(
238  rtems_filesystem_location_info_t *loc,
239  struct stat                      *buf
240)
241{
242   Chain_Node        *the_node;
243   Chain_Control     *the_chain;
244   IMFS_jnode_t      *the_jnode;
245
246
247   the_jnode = (IMFS_jnode_t *) loc->node_access;
248
249   buf->st_dev = 0ll;
250   buf->st_ino   = the_jnode->st_ino;
251   buf->st_mode  = the_jnode->st_mode;
252   buf->st_nlink = the_jnode->st_nlink;
253   buf->st_uid   = the_jnode->st_uid;
254   buf->st_gid   = the_jnode->st_gid;
255   buf->st_rdev = 0ll;
256   buf->st_blksize = 0;
257   buf->st_blocks = 0;
258   buf->st_atime = the_jnode->st_atime;
259   buf->st_mtime = the_jnode->st_mtime;
260   buf->st_ctime = the_jnode->st_ctime;
261
262   buf->st_size = 0;
263
264   the_chain = &the_jnode->info.directory.Entries;
265
266   /* Run through the chain and count the number of directory entries */
267   /* that are subordinate to this directory node                     */
268   for ( the_node = the_chain->first ;
269         !_Chain_Is_tail( the_chain, the_node ) ;
270         the_node = the_node->next ) {
271 
272      buf->st_size = buf->st_size + sizeof( struct dirent );
273   }
274
275   return 0;
276}
277
278
Note: See TracBrowser for help on using the repository browser.