1 |
27 |
unneback |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
|
|
|
32 |
|
|
|
33 |
|
|
File System Support Infrastructure
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
Introduction
|
39 |
|
|
|
40 |
|
|
|
41 |
|
|
This document describes the filesystem infrastructure provided in
|
42 |
|
|
eCos. This is implemented by the FILEIO package and provides POSIX
|
43 |
|
|
compliant file and IO operations together with the BSD socket
|
44 |
|
|
API. These APIs are described in the relevant standards and original
|
45 |
|
|
documentation and will not be described here. See
|
46 |
|
|
linkend="posix-standard-support"> for details of which parts of the
|
47 |
|
|
POSIX standard are supported.
|
48 |
|
|
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
This document is concerned with the interfaces presented to client
|
52 |
|
|
filesystems and network protocol stacks.
|
53 |
|
|
|
54 |
|
|
|
55 |
|
|
|
56 |
|
|
The FILEIO infrastructure consist mainly of a set of tables containing
|
57 |
|
|
pointers to the primary interface functions of a file system. This
|
58 |
|
|
approach avoids problems of namespace pollution (for example several
|
59 |
|
|
filesystems can have a function called read(), so long as they are
|
60 |
|
|
static). The system is also structured to eliminate the need for
|
61 |
|
|
dynamic memory allocation.
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
New filesystems can be written directly to the interfaces described
|
66 |
|
|
here. Existing filesystems can be ported very easily by the
|
67 |
|
|
introduction of a thin veneer porting layer that translates FILEIO
|
68 |
|
|
calls into native filesystem calls.
|
69 |
|
|
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
The term filesystem should be read fairly loosely in this
|
73 |
|
|
document. Object accessed through these interfaces could equally be
|
74 |
|
|
network protocol sockets, device drivers, fifos, message queues or any
|
75 |
|
|
other object that can present a file-like interface.
|
76 |
|
|
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
|
84 |
|
|
File System Table
|
85 |
|
|
|
86 |
|
|
|
87 |
|
|
The filesystem table is an array of entries that describe each
|
88 |
|
|
filesystem implementation that is part of the system image. Each
|
89 |
|
|
resident filesystem should export an entry to this table using the
|
90 |
|
|
FSTAB_ENTRY() macro.
|
91 |
|
|
|
92 |
|
|
|
93 |
|
|
|
94 |
|
|
Note
|
95 |
|
|
|
96 |
|
|
At present we do not support dynamic addition or removal of table
|
97 |
|
|
entries. However, an API similar to mount() would
|
98 |
|
|
allow new entries to be added to the table.
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
The table entries are described by the following structure:
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
|
107 |
|
|
struct cyg_fstab_entry
|
108 |
|
|
{
|
109 |
|
|
const char *name; // filesystem name
|
110 |
|
|
CYG_ADDRWORD data; // private data value
|
111 |
|
|
cyg_uint32 syncmode; // synchronization mode
|
112 |
|
|
|
113 |
|
|
int (*mount) ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
|
114 |
|
|
int (*umount) ( cyg_mtab_entry *mte );
|
115 |
|
|
int (*open) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
116 |
|
|
int mode, cyg_file *fte );
|
117 |
|
|
int (*unlink) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
118 |
|
|
int (*mkdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
119 |
|
|
int (*rmdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
120 |
|
|
int (*rename) ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
|
121 |
|
|
cyg_dir dir2, const char *name2 );
|
122 |
|
|
int (*link) ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
|
123 |
|
|
cyg_dir dir2, const char *name2, int type );
|
124 |
|
|
int (*opendir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
125 |
|
|
cyg_file *fte );
|
126 |
|
|
int (*chdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
127 |
|
|
cyg_dir *dir_out );
|
128 |
|
|
int (*stat) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
129 |
|
|
struct stat *buf);
|
130 |
|
|
int (*getinfo) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
131 |
|
|
int key, char *buf, int len );
|
132 |
|
|
int (*setinfo) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
133 |
|
|
int key, char *buf, int len );
|
134 |
|
|
};
|
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
|
|
The name field points to a string that
|
139 |
|
|
identifies this filesystem implementation. Typical values might be
|
140 |
|
|
"romfs", "msdos", "ext2" etc.
|
141 |
|
|
|
142 |
|
|
|
143 |
|
|
|
144 |
|
|
The data field contains any private data
|
145 |
|
|
that the filesystem needs, perhaps the root of its data structures.
|
146 |
|
|
|
147 |
|
|
|
148 |
|
|
|
149 |
|
|
The syncmode field contains a description of
|
150 |
|
|
the locking protocol to be used when accessing this filesystem. It
|
151 |
|
|
will be described in more detail in .
|
152 |
|
|
|
153 |
|
|
|
154 |
|
|
|
155 |
|
|
The remaining fields are pointers to functions that implement
|
156 |
|
|
filesystem operations that apply to files and directories as whole
|
157 |
|
|
objects. The operation implemented by each function should be obvious
|
158 |
|
|
from the names, with a few exceptions:
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
|
162 |
|
|
The opendir() function pointer opens a directory
|
163 |
|
|
for reading. See for details.
|
164 |
|
|
|
165 |
|
|
|
166 |
|
|
|
167 |
|
|
The getinfo() and
|
168 |
|
|
setinfo() function pointers provide support for
|
169 |
|
|
various minor control and information functions such as
|
170 |
|
|
pathconf() and access().
|
171 |
|
|
|
172 |
|
|
|
173 |
|
|
|
174 |
|
|
With the exception of the mount() and
|
175 |
|
|
umount() functions, all of these functions
|
176 |
|
|
take three standard arguments, a pointer to a mount table entry (see
|
177 |
|
|
later) a directory pointer (also see later) and a file name relative
|
178 |
|
|
to the directory. These should be used by the filesystem to locate the
|
179 |
|
|
object of interest.
|
180 |
|
|
|
181 |
|
|
|
182 |
|
|
|
183 |
|
|
|
184 |
|
|
|
185 |
|
|
|
186 |
|
|
|
187 |
|
|
|
188 |
|
|
Mount Table
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
The mount table records the filesystems that are actually active.
|
192 |
|
|
These can be seen as being analogous to mount points in Unix systems.
|
193 |
|
|
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
There are two sources of mount table entries. Filesystems (or other
|
197 |
|
|
components) may export static entries to the table using the
|
198 |
|
|
MTAB_ENTRY() macro. Alternatively, new entries may
|
199 |
|
|
be installed at run time using the mount()
|
200 |
|
|
function. Both types of entry may be unmounted with the
|
201 |
|
|
umount() function.
|
202 |
|
|
|
203 |
|
|
|
204 |
|
|
|
205 |
|
|
A mount table entry has the following structure:
|
206 |
|
|
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
struct cyg_mtab_entry
|
210 |
|
|
{
|
211 |
|
|
const char *name; // name of mount point
|
212 |
|
|
const char *fsname; // name of implementing filesystem
|
213 |
|
|
const char *devname; // name of hardware device
|
214 |
|
|
CYG_ADDRWORD data; // private data value
|
215 |
|
|
cyg_bool valid; // Valid entry?
|
216 |
|
|
cyg_fstab_entry *fs; // pointer to fstab entry
|
217 |
|
|
cyg_dir root; // root directory pointer
|
218 |
|
|
};
|
219 |
|
|
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
The name field identifies the mount
|
223 |
|
|
point. This is used to direct rooted filenames (filenames that
|
224 |
|
|
begin with "/") to the correct filesystem. When a file
|
225 |
|
|
name that begins with "/" is submitted, it is matched
|
226 |
|
|
against the name fields of all valid mount
|
227 |
|
|
table entries. The entry that yields the longest match terminating
|
228 |
|
|
before a "/", or end of string, wins and the appropriate
|
229 |
|
|
function from the filesystem table entry is then passed the remainder
|
230 |
|
|
of the file name together with a pointer to the table entry and the
|
231 |
|
|
value of the root field as the directory
|
232 |
|
|
pointer.
|
233 |
|
|
|
234 |
|
|
|
235 |
|
|
|
236 |
|
|
For example, consider a mount table that contains the following
|
237 |
|
|
entries:
|
238 |
|
|
|
239 |
|
|
|
240 |
|
|
|
241 |
|
|
{ "/", "msdos", "/dev/hd0", ... }
|
242 |
|
|
{ "/fd", "msdos", "/dev/fd0", ... }
|
243 |
|
|
{ "/rom", "romfs", "", ... }
|
244 |
|
|
{ "/tmp", "ramfs", "", ... }
|
245 |
|
|
{ "/dev", "devfs", "", ... }
|
246 |
|
|
|
247 |
|
|
|
248 |
|
|
|
249 |
|
|
An attempt to open "/tmp/foo" would be directed to the RAM
|
250 |
|
|
filesystem while an open of "/bar/bundy" would be directed
|
251 |
|
|
to the hard disc MSDOS filesystem. Opening "/dev/tty0" would
|
252 |
|
|
be directed to the device management filesystem for lookup in the
|
253 |
|
|
device table.
|
254 |
|
|
|
255 |
|
|
|
256 |
|
|
|
257 |
|
|
Unrooted file names (those that do not begin with a '/') are passed
|
258 |
|
|
straight to the filesystem that contains the current directory. The
|
259 |
|
|
current directory is represented by a pair consisting of a mount table
|
260 |
|
|
entry and a directory pointer.
|
261 |
|
|
|
262 |
|
|
|
263 |
|
|
|
264 |
|
|
The fsname field points to a string that
|
265 |
|
|
should match the name field of the
|
266 |
|
|
implementing filesystem. During initialization the mount table is
|
267 |
|
|
scanned and the fsname entries looked up in
|
268 |
|
|
the filesystem table. For each match, the filesystem's _mount_
|
269 |
|
|
function is called and if successful the mount table entry is marked
|
270 |
|
|
as valid and the fs pointer installed.
|
271 |
|
|
|
272 |
|
|
|
273 |
|
|
|
274 |
|
|
The devname field contains the name of the
|
275 |
|
|
device that this filesystem is to use. This may match an entry in the
|
276 |
|
|
device table (see later) or may be a string that is specific to the
|
277 |
|
|
filesystem if it has its own internal device drivers.
|
278 |
|
|
|
279 |
|
|
|
280 |
|
|
|
281 |
|
|
The data field is a private data value. This
|
282 |
|
|
may be installed either statically when the table entry is defined, or
|
283 |
|
|
may be installed during the mount() operation.
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
The valid field indicates whether this mount
|
288 |
|
|
point has actually been mounted successfully. Entries with a false
|
289 |
|
|
valid field are ignored when searching for a
|
290 |
|
|
name match.
|
291 |
|
|
|
292 |
|
|
|
293 |
|
|
|
294 |
|
|
The fs field is installed after a successful
|
295 |
|
|
mount() operation to point to the implementing
|
296 |
|
|
filesystem.
|
297 |
|
|
|
298 |
|
|
|
299 |
|
|
|
300 |
|
|
The root field contains a directory pointer
|
301 |
|
|
value that the filesystem can interpret as the root of its directory
|
302 |
|
|
tree. This is passed as the dir argument of
|
303 |
|
|
filesystem functions that operate on rooted filenames. This field must
|
304 |
|
|
be initialized by the filesystem's mount()
|
305 |
|
|
function.
|
306 |
|
|
|
307 |
|
|
|
308 |
|
|
|
309 |
|
|
|
310 |
|
|
|
311 |
|
|
|
312 |
|
|
|
313 |
|
|
|
314 |
|
|
File Table
|
315 |
|
|
|
316 |
|
|
|
317 |
|
|
Once a file has been opened it is represented by an open file
|
318 |
|
|
object. These are allocated from an array of available file
|
319 |
|
|
objects. User code accesses these open file objects via a second array
|
320 |
|
|
of pointers which is indexed by small integer offsets. This gives the
|
321 |
|
|
usual Unix file descriptor functionality, complete with the various
|
322 |
|
|
duplication mechanisms.
|
323 |
|
|
|
324 |
|
|
|
325 |
|
|
|
326 |
|
|
A file table entry has the following structure:
|
327 |
|
|
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
struct CYG_FILE_TAG
|
331 |
|
|
{
|
332 |
|
|
cyg_uint32 f_flag; /* file state */
|
333 |
|
|
cyg_uint16 f_ucount; /* use count */
|
334 |
|
|
cyg_uint16 f_type; /* descriptor type */
|
335 |
|
|
cyg_uint32 f_syncmode; /* synchronization protocol */
|
336 |
|
|
struct CYG_FILEOPS_TAG *f_ops; /* file operations */
|
337 |
|
|
off_t f_offset; /* current offset */
|
338 |
|
|
CYG_ADDRWORD f_data; /* file or socket */
|
339 |
|
|
CYG_ADDRWORD f_xops; /* extra type specific ops */
|
340 |
|
|
cyg_mtab_entry *f_mte; /* mount table entry */
|
341 |
|
|
};
|
342 |
|
|
|
343 |
|
|
|
344 |
|
|
|
345 |
|
|
The f_flag field contains some FILEIO
|
346 |
|
|
control bits and some bits propagated from the
|
347 |
|
|
flags argument of the
|
348 |
|
|
open() call (defined by
|
349 |
|
|
CYG_FILE_MODE_MASK).
|
350 |
|
|
|
351 |
|
|
|
352 |
|
|
|
353 |
|
|
The f_ucount field contains a use count that
|
354 |
|
|
controls when a file will be closed. Each duplicate in the file
|
355 |
|
|
descriptor array counts for one reference here. It is also
|
356 |
|
|
incremented around each I/O operation to ensure that the file cannot
|
357 |
|
|
be closed while it has current I/O operations.
|
358 |
|
|
|
359 |
|
|
|
360 |
|
|
|
361 |
|
|
The f_type field indicates the type of the
|
362 |
|
|
underlying file object. Some of the possible values here are
|
363 |
|
|
CYG_FILE_TYPE_FILE,
|
364 |
|
|
CYG_FILE_TYPE_SOCKET or CYG_FILE_TYPE_DEVICE.
|
365 |
|
|
|
366 |
|
|
|
367 |
|
|
|
368 |
|
|
The f_syncmode field is copied from the
|
369 |
|
|
syncmode field of the implementing
|
370 |
|
|
filesystem. Its use is described in .
|
371 |
|
|
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
The f_offset field records the current file
|
375 |
|
|
position. It is the responsibility of the file operation functions to
|
376 |
|
|
keep this field up to date.
|
377 |
|
|
|
378 |
|
|
|
379 |
|
|
|
380 |
|
|
The f_data field contains private data
|
381 |
|
|
placed here by the underlying filesystem. Normally this will be a
|
382 |
|
|
pointer to, or handle on, the filesystem object that implements this
|
383 |
|
|
file.
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
|
387 |
|
|
The f_xops field contains a pointer to any
|
388 |
|
|
extra type specific operation functions. For example, the socket I/O
|
389 |
|
|
system installs a pointer to a table of functions that implement the
|
390 |
|
|
standard socket operations.
|
391 |
|
|
|
392 |
|
|
|
393 |
|
|
|
394 |
|
|
The f_mte field contains a pointer to the
|
395 |
|
|
parent mount table entry for this file. It is used mainly to implement
|
396 |
|
|
the synchronization protocol. This may contain a pointer to some other
|
397 |
|
|
data structure in file objects not derived from a filesystem.
|
398 |
|
|
|
399 |
|
|
|
400 |
|
|
|
401 |
|
|
The f_ops field contains a pointer to a
|
402 |
|
|
table of file I/O operations. This has the following structure:
|
403 |
|
|
|
404 |
|
|
|
405 |
|
|
|
406 |
|
|
struct CYG_FILEOPS_TAG
|
407 |
|
|
{
|
408 |
|
|
int (*fo_read) (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
|
409 |
|
|
int (*fo_write) (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
|
410 |
|
|
int (*fo_lseek) (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
|
411 |
|
|
int (*fo_ioctl) (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
|
412 |
|
|
CYG_ADDRWORD data);
|
413 |
|
|
int (*fo_select) (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);
|
414 |
|
|
int (*fo_fsync) (struct CYG_FILE_TAG *fp, int mode );
|
415 |
|
|
int (*fo_close) (struct CYG_FILE_TAG *fp);
|
416 |
|
|
int (*fo_fstat) (struct CYG_FILE_TAG *fp, struct stat *buf );
|
417 |
|
|
int (*fo_getinfo) (struct CYG_FILE_TAG *fp, int key, char *buf, int len );
|
418 |
|
|
int (*fo_setinfo) (struct CYG_FILE_TAG *fp, int key, char *buf, int len );
|
419 |
|
|
};
|
420 |
|
|
|
421 |
|
|
|
422 |
|
|
|
423 |
|
|
It should be obvious from the names of most of these functions what
|
424 |
|
|
their responsibilities are. The fo_getinfo()
|
425 |
|
|
and fo_setinfo() function pointers, like their
|
426 |
|
|
counterparts in the filesystem structure, implement minor control and
|
427 |
|
|
info functions such as fpathconf().
|
428 |
|
|
|
429 |
|
|
|
430 |
|
|
|
431 |
|
|
The second argument to the fo_read() and
|
432 |
|
|
fo_write() function pointers is a pointer to a
|
433 |
|
|
UIO structure:
|
434 |
|
|
|
435 |
|
|
|
436 |
|
|
|
437 |
|
|
struct CYG_UIO_TAG
|
438 |
|
|
{
|
439 |
|
|
struct CYG_IOVEC_TAG *uio_iov; /* pointer to array of iovecs */
|
440 |
|
|
int uio_iovcnt; /* number of iovecs in array */
|
441 |
|
|
off_t uio_offset; /* offset into file this uio corresponds to */
|
442 |
|
|
ssize_t uio_resid; /* residual i/o count */
|
443 |
|
|
enum cyg_uio_seg uio_segflg; /* see above */
|
444 |
|
|
enum cyg_uio_rw uio_rw; /* see above */
|
445 |
|
|
};
|
446 |
|
|
|
447 |
|
|
struct CYG_IOVEC_TAG
|
448 |
|
|
{
|
449 |
|
|
void *iov_base; /* Base address. */
|
450 |
|
|
ssize_t iov_len; /* Length. */
|
451 |
|
|
};
|
452 |
|
|
|
453 |
|
|
|
454 |
|
|
|
455 |
|
|
This structure encapsulates the parameters of any data transfer
|
456 |
|
|
operation. It provides support for scatter/gather operations and
|
457 |
|
|
records the progress of any data transfer. It is also compatible with
|
458 |
|
|
the I/O operations of any BSD-derived network stacks and filesystems.
|
459 |
|
|
|
460 |
|
|
|
461 |
|
|
|
462 |
|
|
When a file is opened (or a file object created by some other means,
|
463 |
|
|
such as socket() or accept()) it is the
|
464 |
|
|
responsibility of the filesystem open operation to initialize all the
|
465 |
|
|
fields of the object except the f_ucount,
|
466 |
|
|
f_syncmode and
|
467 |
|
|
f_mte fields. Since the
|
468 |
|
|
f_flag field will already contain bits belonging to the FILEIO
|
469 |
|
|
infrastructure, any changes to it must be made with the appropriate
|
470 |
|
|
logical operations.
|
471 |
|
|
|
472 |
|
|
|
473 |
|
|
|
474 |
|
|
|
475 |
|
|
|
476 |
|
|
|
477 |
|
|
|
478 |
|
|
|
479 |
|
|
Directories
|
480 |
|
|
|
481 |
|
|
|
482 |
|
|
Filesystem operations all take a directory pointer as one of their
|
483 |
|
|
arguments. A directory pointer is an opaque handle managed by the
|
484 |
|
|
filesystem. It should encapsulate a reference to a specific directory
|
485 |
|
|
within the filesystem. For example, it may be a pointer to the data
|
486 |
|
|
structure that represents that directory (such as an inode), or a
|
487 |
|
|
pointer to a pathname for the directory.
|
488 |
|
|
|
489 |
|
|
|
490 |
|
|
|
491 |
|
|
The chdir() filesystem function pointer has two
|
492 |
|
|
modes of use. When passed a pointer in the
|
493 |
|
|
dir_out argument, it should locate the named
|
494 |
|
|
directory and place a directory pointer there. If the
|
495 |
|
|
dir_out argument is NULL then the
|
496 |
|
|
dir argument is a previously generated
|
497 |
|
|
directory pointer that can now be disposed of. When the infrastructure
|
498 |
|
|
is implementing the chdir() function it makes two
|
499 |
|
|
calls to filesystem chdir() functions. The first
|
500 |
|
|
is to get a directory pointer for the new current directory. If this
|
501 |
|
|
succeeds the second is to dispose of the old current directory
|
502 |
|
|
pointer.
|
503 |
|
|
|
504 |
|
|
|
505 |
|
|
|
506 |
|
|
The opendir() function is used to open a
|
507 |
|
|
directory for reading. This results in an open file object that can be
|
508 |
|
|
read to return a sequence of struct dirent
|
509 |
|
|
objects. The only operations that are allowed on this file are
|
510 |
|
|
read, lseek and
|
511 |
|
|
close. Each read operation on this file should
|
512 |
|
|
return a single struct dirent object. When
|
513 |
|
|
the end of the directory is reached, zero should be returned. The only
|
514 |
|
|
seek operation allowed is a rewind to the start of the directory, by
|
515 |
|
|
supplying an offset of zero and a whence
|
516 |
|
|
specifier of SEEK_SET.
|
517 |
|
|
|
518 |
|
|
|
519 |
|
|
|
520 |
|
|
Most of these considerations are invisible to clients of a filesystem
|
521 |
|
|
since they will access directories via the POSIX
|
522 |
|
|
opendir(), readdir() and
|
523 |
|
|
closedir() functions.
|
524 |
|
|
|
525 |
|
|
|
526 |
|
|
|
527 |
|
|
Support for the getcwd() function is provided by
|
528 |
|
|
three mechanisms. The first is to use the
|
529 |
|
|
FS_INFO_GETCWD getinfo key on the filesystem to use
|
530 |
|
|
any internal support that it has for this. If that fails it falls back
|
531 |
|
|
on one of the two other mechanisms. If
|
532 |
|
|
CYGPKG_IO_FILEIO_TRACK_CWD is set then the current
|
533 |
|
|
directory is tracked textually in chdir() and the result of that is
|
534 |
|
|
reported in getcwd(). Otherwise an attempt is made to traverse the
|
535 |
|
|
directory tree to its root using ".." entries.
|
536 |
|
|
|
537 |
|
|
|
538 |
|
|
|
539 |
|
|
This last option is complicated and expensive, and relies on the
|
540 |
|
|
filesystem supporting "." and ".." entries. This is not always the
|
541 |
|
|
case, particularly if the filesystem has been ported from a
|
542 |
|
|
non-UNIX-compatible source. Tracking the pathname textually will
|
543 |
|
|
usually work, but might not produce optimum results when symbolic
|
544 |
|
|
links are being used.
|
545 |
|
|
|
546 |
|
|
|
547 |
|
|
|
548 |
|
|
|
549 |
|
|
|
550 |
|
|
|
551 |
|
|
|
552 |
|
|
|
553 |
|
|
Synchronization
|
554 |
|
|
|
555 |
|
|
|
556 |
|
|
The FILEIO infrastructure provides a synchronization mechanism for
|
557 |
|
|
controlling concurrent access to filesystems. This allows existing
|
558 |
|
|
filesystems to be ported to eCos, even if they do not have their own
|
559 |
|
|
synchronization mechanisms. It also allows new filesystems to be
|
560 |
|
|
implemented easily without having to consider the synchronization
|
561 |
|
|
issues.
|
562 |
|
|
|
563 |
|
|
|
564 |
|
|
|
565 |
|
|
The infrastructure maintains a mutex for each entry in each of
|
566 |
|
|
the main tables: filesystem table, mount table and file table. For
|
567 |
|
|
each class of operation each of these mutexes may be locked before the
|
568 |
|
|
corresponding filesystem operation is invoked.
|
569 |
|
|
|
570 |
|
|
|
571 |
|
|
|
572 |
|
|
The synchronization protocol required by a filesystem is described
|
573 |
|
|
by the syncmode field of the filesystem
|
574 |
|
|
table entry. This is a combination of the following flags:
|
575 |
|
|
|
576 |
|
|
|
577 |
|
|
|
578 |
|
|
|
579 |
|
|
CYG_SYNCMODE_FILE_FILESYSTEM
|
580 |
|
|
|
581 |
|
|
|
582 |
|
|
Lock the filesystem table entry mutex
|
583 |
|
|
during all filesystem level operations.
|
584 |
|
|
|
585 |
|
|
|
586 |
|
|
|
587 |
|
|
|
588 |
|
|
|
589 |
|
|
CYG_SYNCMODE_FILE_MOUNTPOINT
|
590 |
|
|
|
591 |
|
|
|
592 |
|
|
Lock the mount table entry mutex
|
593 |
|
|
during all filesystem level operations.
|
594 |
|
|
|
595 |
|
|
|
596 |
|
|
|
597 |
|
|
|
598 |
|
|
|
599 |
|
|
CYG_SYNCMODE_IO_FILE
|
600 |
|
|
|
601 |
|
|
|
602 |
|
|
Lock the file table entry mutex during all
|
603 |
|
|
I/O operations.
|
604 |
|
|
|
605 |
|
|
|
606 |
|
|
|
607 |
|
|
|
608 |
|
|
|
609 |
|
|
CYG_SYNCMODE_IO_FILESYSTEM
|
610 |
|
|
|
611 |
|
|
|
612 |
|
|
Lock the filesystem table entry mutex during all I/O operations.
|
613 |
|
|
|
614 |
|
|
|
615 |
|
|
|
616 |
|
|
|
617 |
|
|
|
618 |
|
|
CYG_SYNCMODE_IO_MOUNTPOINT
|
619 |
|
|
|
620 |
|
|
Lock the mount table entry mutex during all I/O operations.
|
621 |
|
|
|
622 |
|
|
|
623 |
|
|
|
624 |
|
|
|
625 |
|
|
|
626 |
|
|
CYG_SYNCMODE_SOCK_FILE
|
627 |
|
|
|
628 |
|
|
|
629 |
|
|
Lock the file table entry mutex during all socket operations.
|
630 |
|
|
|
631 |
|
|
|
632 |
|
|
|
633 |
|
|
|
634 |
|
|
|
635 |
|
|
CYG_SYNCMODE_SOCK_NETSTACK
|
636 |
|
|
|
637 |
|
|
|
638 |
|
|
Lock the network stack table entry mutex during all socket operations.
|
639 |
|
|
|
640 |
|
|
|
641 |
|
|
|
642 |
|
|
|
643 |
|
|
|
644 |
|
|
CYG_SYNCMODE_NONE
|
645 |
|
|
|
646 |
|
|
|
647 |
|
|
Perform no locking at all during any operations.
|
648 |
|
|
|
649 |
|
|
|
650 |
|
|
|
651 |
|
|
|
652 |
|
|
|
653 |
|
|
|
654 |
|
|
|
655 |
|
|
The value of the syncmode field in the
|
656 |
|
|
filesystem table entry will be copied by the infrastructure to the
|
657 |
|
|
open file object after a successful open() operation.
|
658 |
|
|
|
659 |
|
|
|
660 |
|
|
|
661 |
|
|
|
662 |
|
|
|
663 |
|
|
|
664 |
|
|
|
665 |
|
|
|
666 |
|
|
Initialization and Mounting
|
667 |
|
|
|
668 |
|
|
|
669 |
|
|
As mentioned previously, mount table entries can be sourced from two
|
670 |
|
|
places. Static entries may be defined by using the
|
671 |
|
|
MTAB_ENTRY() macro. Such entries will be
|
672 |
|
|
automatically mounted on system startup. For each entry in the mount
|
673 |
|
|
table that has a non-null name field the
|
674 |
|
|
filesystem table is searched for a match with the
|
675 |
|
|
fsname field. If a match is found the
|
676 |
|
|
filesystem's mount entry is called and if
|
677 |
|
|
successful the mount table entry marked valid and the
|
678 |
|
|
fs field initialized. The
|
679 |
|
|
mount() function is responsible for initializing
|
680 |
|
|
the root field.
|
681 |
|
|
|
682 |
|
|
|
683 |
|
|
|
684 |
|
|
|
685 |
|
|
The size of the mount table is defined by the configuration value
|
686 |
|
|
CYGNUM_FILEIO_MTAB_MAX. Any entries that have not
|
687 |
|
|
been statically defined are available for use by dynamic mounts.
|
688 |
|
|
|
689 |
|
|
|
690 |
|
|
|
691 |
|
|
A filesystem may be mounted dynamically by calling mount(). This
|
692 |
|
|
function has the following prototype:
|
693 |
|
|
|
694 |
|
|
|
695 |
|
|
|
696 |
|
|
int mount( const char *devname,
|
697 |
|
|
const char *dir,
|
698 |
|
|
const char *fsname);
|
699 |
|
|
|
700 |
|
|
|
701 |
|
|
|
702 |
|
|
The devname argument identifies a device that
|
703 |
|
|
will be used by this filesystem and will be assigned to the
|
704 |
|
|
devname field of the mount table entry.
|
705 |
|
|
|
706 |
|
|
|
707 |
|
|
|
708 |
|
|
The dir argument is the mount point name, it
|
709 |
|
|
will be assigned to the name field of the
|
710 |
|
|
mount table entry.
|
711 |
|
|
|
712 |
|
|
|
713 |
|
|
|
714 |
|
|
The fsname argument is the name of the
|
715 |
|
|
implementing filesystem, it will be assigned to the
|
716 |
|
|
fsname entry of the mount table entry.
|
717 |
|
|
|
718 |
|
|
|
719 |
|
|
|
720 |
|
|
The process of mounting a filesystem dynamically is as follows. First
|
721 |
|
|
a search is made of the mount table for an entry with a NULL
|
722 |
|
|
name field to be used for the new mount
|
723 |
|
|
point. The filesystem table is then searched for an entry whose name
|
724 |
|
|
matches fsname. If this is successful then
|
725 |
|
|
the mount table entry is initialized and the filesystem's
|
726 |
|
|
mount() operation called. If this is successful,
|
727 |
|
|
the mount table entry is marked valid and the
|
728 |
|
|
fs field initialized.
|
729 |
|
|
|
730 |
|
|
|
731 |
|
|
|
732 |
|
|
Unmounting a filesystem is done by the umount()
|
733 |
|
|
function. This can unmount filesystems whether they were mounted
|
734 |
|
|
statically or dynamically.
|
735 |
|
|
|
736 |
|
|
|
737 |
|
|
|
738 |
|
|
The umount() function has the following prototype:
|
739 |
|
|
|
740 |
|
|
|
741 |
|
|
|
742 |
|
|
int umount( const char *name );
|
743 |
|
|
|
744 |
|
|
|
745 |
|
|
|
746 |
|
|
The mount table is searched for a match between the
|
747 |
|
|
name argument and the entry
|
748 |
|
|
name field. When a match is found the
|
749 |
|
|
filesystem's umount() operation is called and if
|
750 |
|
|
successful, the mount table entry is invalidated by setting its
|
751 |
|
|
valid field false and the
|
752 |
|
|
name field to NULL.
|
753 |
|
|
|
754 |
|
|
|
755 |
|
|
|
759 |
|
|
|
760 |
|
|
|
761 |
|
|
|
762 |
|
|
|
763 |
|
|
|
764 |
|
|
|
765 |
|
|
|
766 |
|
|
Sockets
|
767 |
|
|
|
768 |
|
|
|
769 |
|
|
If a network stack is present, then the FILEIO infrastructure also
|
770 |
|
|
provides access to the standard BSD socket calls.
|
771 |
|
|
|
772 |
|
|
|
773 |
|
|
|
774 |
|
|
The netstack table contains entries which describe the network
|
775 |
|
|
protocol stacks that are in the system image. Each resident stack
|
776 |
|
|
should export an entry to this table using the
|
777 |
|
|
NSTAB_ENTRY() macro.
|
778 |
|
|
|
779 |
|
|
|
780 |
|
|
|
781 |
|
|
Each table entry has the following structure:
|
782 |
|
|
|
783 |
|
|
|
784 |
|
|
|
785 |
|
|
struct cyg_nstab_entry
|
786 |
|
|
{
|
787 |
|
|
cyg_bool valid; // true if stack initialized
|
788 |
|
|
cyg_uint32 syncmode; // synchronization protocol
|
789 |
|
|
char *name; // stack name
|
790 |
|
|
char *devname; // hardware device name
|
791 |
|
|
CYG_ADDRWORD data; // private data value
|
792 |
|
|
|
793 |
|
|
int (*init)( cyg_nstab_entry *nste );
|
794 |
|
|
int (*socket)( cyg_nstab_entry *nste, int domain, int type,
|
795 |
|
|
int protocol, cyg_file *file );
|
796 |
|
|
};
|
797 |
|
|
|
798 |
|
|
|
799 |
|
|
|
800 |
|
|
This table is analogous to a combination of the filesystem and mount
|
801 |
|
|
tables.
|
802 |
|
|
|
803 |
|
|
|
804 |
|
|
|
805 |
|
|
The valid field is set
|
806 |
|
|
true if the stack's init()
|
807 |
|
|
function returned successfully and the
|
808 |
|
|
syncmode field contains the
|
809 |
|
|
CYG_SYNCMODE_SOCK_* bits described above.
|
810 |
|
|
|
811 |
|
|
|
812 |
|
|
|
816 |
|
|
|
817 |
|
|
|
818 |
|
|
The name field contains the name of the
|
819 |
|
|
protocol stack.
|
820 |
|
|
|
821 |
|
|
|
822 |
|
|
|
826 |
|
|
|
827 |
|
|
|
828 |
|
|
The devname field names the device that the stack is using. This may
|
829 |
|
|
reference a device under "/dev", or may be a name that is only
|
830 |
|
|
meaningful to the stack itself.
|
831 |
|
|
|
832 |
|
|
|
833 |
|
|
|
837 |
|
|
|
838 |
|
|
|
839 |
|
|
The init() function pointer is called during
|
840 |
|
|
system initialization to start the protocol stack running. If it
|
841 |
|
|
returns non-zero the valid field is set
|
842 |
|
|
false and the stack will be ignored subsequently.
|
843 |
|
|
|
844 |
|
|
|
845 |
|
|
|
846 |
|
|
The socket() function is called to attempt to create a socket in the
|
847 |
|
|
stack. When the socket() API function is called the netstack table is
|
848 |
|
|
scanned and for each valid entry the socket()
|
849 |
|
|
function pointer is called. If
|
850 |
|
|
this returns non-zero then the scan continues to the next valid stack,
|
851 |
|
|
or terminates with an error if the end of the table is reached.
|
852 |
|
|
|
853 |
|
|
|
854 |
|
|
|
855 |
|
|
The result of a successful socket call is an initialized file object
|
856 |
|
|
with the f_xops field pointing to the
|
857 |
|
|
following structure:
|
858 |
|
|
|
859 |
|
|
|
860 |
|
|
|
861 |
|
|
struct cyg_sock_ops
|
862 |
|
|
{
|
863 |
|
|
int (*bind) ( cyg_file *fp, const sockaddr *sa, socklen_t len );
|
864 |
|
|
int (*connect) ( cyg_file *fp, const sockaddr *sa, socklen_t len );
|
865 |
|
|
int (*accept) ( cyg_file *fp, cyg_file *new_fp,
|
866 |
|
|
struct sockaddr *name, socklen_t *anamelen );
|
867 |
|
|
int (*listen) ( cyg_file *fp, int len );
|
868 |
|
|
int (*getname) ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );
|
869 |
|
|
int (*shutdown) ( cyg_file *fp, int flags );
|
870 |
|
|
int (*getsockopt)( cyg_file *fp, int level, int optname,
|
871 |
|
|
void *optval, socklen_t *optlen);
|
872 |
|
|
int (*setsockopt)( cyg_file *fp, int level, int optname,
|
873 |
|
|
const void *optval, socklen_t optlen);
|
874 |
|
|
int (*sendmsg) ( cyg_file *fp, const struct msghdr *m,
|
875 |
|
|
int flags, ssize_t *retsize );
|
876 |
|
|
int (*recvmsg) ( cyg_file *fp, struct msghdr *m,
|
877 |
|
|
socklen_t *namelen, ssize_t *retsize );
|
878 |
|
|
};
|
879 |
|
|
|
880 |
|
|
|
881 |
|
|
|
882 |
|
|
It should be obvious from the names of these functions which API calls
|
883 |
|
|
they provide support for. The getname() function
|
884 |
|
|
pointer provides support for both getsockname()
|
885 |
|
|
and getpeername() while the
|
886 |
|
|
sendmsg() and recvmsg()
|
887 |
|
|
function pointers provide support for send(),
|
888 |
|
|
sendto(), sendmsg(),
|
889 |
|
|
recv(), recvfrom() and
|
890 |
|
|
recvmsg() as appropriate.
|
891 |
|
|
|
892 |
|
|
|
893 |
|
|
|
894 |
|
|
|
895 |
|
|
|
896 |
|
|
|
897 |
|
|
|
898 |
|
|
|
899 |
|
|
Select
|
900 |
|
|
|
901 |
|
|
|
902 |
|
|
The infrastructure provides support for implementing a select
|
903 |
|
|
mechanism. This is modeled on the mechanism in the BSD kernel, but has
|
904 |
|
|
been modified to make it implementation independent.
|
905 |
|
|
|
906 |
|
|
|
907 |
|
|
|
908 |
|
|
The main part of the mechanism is the select()
|
909 |
|
|
API call. This processes its arguments and calls the
|
910 |
|
|
fo_select() function pointer on all file objects
|
911 |
|
|
referenced by the file descriptor sets passed to it. If the same
|
912 |
|
|
descriptor appears in more than one descriptor set, the
|
913 |
|
|
fo_select() function will be called separately
|
914 |
|
|
for each appearance.
|
915 |
|
|
|
916 |
|
|
|
917 |
|
|
|
918 |
|
|
The which argument of the
|
919 |
|
|
fo_select() function will either be
|
920 |
|
|
CYG_FREAD to test for read conditions,
|
921 |
|
|
CYG_FWRITE to test for write conditions or zero to
|
922 |
|
|
test for exceptions. For each of these options the function should
|
923 |
|
|
test whether the condition is satisfied and if so return true. If it
|
924 |
|
|
is not satisfied then it should call
|
925 |
|
|
cyg_selrecord() with the
|
926 |
|
|
info argument that was passed to the function
|
927 |
|
|
and a pointer to a cyg_selinfo structure.
|
928 |
|
|
|
929 |
|
|
|
930 |
|
|
|
931 |
|
|
The cyg_selinfo structure is used to record information about current
|
932 |
|
|
select operations. Any object that needs to support select must
|
933 |
|
|
contain an instance of this structure. Separate cyg_selinfo
|
934 |
|
|
structures should be kept for each of the options that the object can
|
935 |
|
|
select on - read, write or exception.
|
936 |
|
|
|
937 |
|
|
|
938 |
|
|
|
939 |
|
|
If none of the file objects report that the select condition is
|
940 |
|
|
satisfied, then the select() API function puts
|
941 |
|
|
the calling thread to sleep waiting either for a condition to become
|
942 |
|
|
satisfied, or for the optional timeout to expire.
|
943 |
|
|
|
944 |
|
|
|
945 |
|
|
|
946 |
|
|
A selectable object must have some asynchronous activity that may
|
947 |
|
|
cause a select condition to become true - either via interrupts or the
|
948 |
|
|
activities of other threads. Whenever a selectable condition is
|
949 |
|
|
satisfied, the object should call cyg_selwakeup() with a pointer to
|
950 |
|
|
the appropriate cyg_selinfo structure. If the thread is still waiting,
|
951 |
|
|
this will cause it to wake up and repeat its poll of the file
|
952 |
|
|
descriptors. This time around, the object that caused the wakeup
|
953 |
|
|
should indicate that the select condition is satisfied, and the
|
954 |
|
|
select() API call will return.
|
955 |
|
|
|
956 |
|
|
|
957 |
|
|
|
958 |
|
|
Note that select() does not exhibit real time
|
959 |
|
|
behaviour: the iterative poll of the descriptors, and the wakeup
|
960 |
|
|
mechanism mitigate against this. If real time response to device or
|
961 |
|
|
socket I/O is required then separate threads should be devoted to each
|
962 |
|
|
device of interest and should use blocking calls to wait for a
|
963 |
|
|
condition to become ready.
|
964 |
|
|
|
965 |
|
|
|
966 |
|
|
|
967 |
|
|
|
968 |
|
|
|
969 |
|
|
|
970 |
|
|
|
971 |
|
|
|
972 |
|
|
Devices
|
973 |
|
|
|
974 |
|
|
|
975 |
|
|
Devices are accessed by means of a pseudo-filesystem, "devfs", that is
|
976 |
|
|
mounted on "/dev". Open operations are translated into calls to
|
977 |
|
|
cyg_io_lookup() and if successful result in a file object whose
|
978 |
|
|
f_ops functions translate filesystem API functions into calls into
|
979 |
|
|
the device API.
|
980 |
|
|
|
981 |
|
|
|
982 |
|
|
|
983 |
|
|
|
984 |
|
|
|
985 |
|
|
|
986 |
|
|
|
987 |
|
|
|
988 |
|
|
Writing a New Filesystem
|
989 |
|
|
|
990 |
|
|
|
991 |
|
|
To create a new filesystem it is necessary to define the fstab entry
|
992 |
|
|
and the file IO operations. The easiest way to do this is to copy an
|
993 |
|
|
existing filesystem: either the test filesystem in the FILEIO package,
|
994 |
|
|
or the RAM or ROM filesystem packages.
|
995 |
|
|
|
996 |
|
|
|
997 |
|
|
|
998 |
|
|
To make this clearer, the following is a brief tour of the FILEIO
|
999 |
|
|
relevant parts of the RAM filesystem.
|
1000 |
|
|
|
1001 |
|
|
|
1002 |
|
|
|
1003 |
|
|
First, it is necessary to provide forward definitions of the functions
|
1004 |
|
|
that constitute the filesystem interface:
|
1005 |
|
|
|
1006 |
|
|
|
1007 |
|
|
|
1008 |
|
|
//==========================================================================
|
1009 |
|
|
// Forward definitions
|
1010 |
|
|
|
1011 |
|
|
// Filesystem operations
|
1012 |
|
|
static int ramfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
|
1013 |
|
|
static int ramfs_umount ( cyg_mtab_entry *mte );
|
1014 |
|
|
static int ramfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1015 |
|
|
int mode, cyg_file *fte );
|
1016 |
|
|
static int ramfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
1017 |
|
|
static int ramfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
1018 |
|
|
static int ramfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
|
1019 |
|
|
static int ramfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
|
1020 |
|
|
cyg_dir dir2, const char *name2 );
|
1021 |
|
|
static int ramfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
|
1022 |
|
|
cyg_dir dir2, const char *name2, int type );
|
1023 |
|
|
static int ramfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1024 |
|
|
cyg_file *fte );
|
1025 |
|
|
static int ramfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1026 |
|
|
cyg_dir *dir_out );
|
1027 |
|
|
static int ramfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1028 |
|
|
struct stat *buf);
|
1029 |
|
|
static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1030 |
|
|
int key, void *buf, int len );
|
1031 |
|
|
static int ramfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
1032 |
|
|
int key, void *buf, int len );
|
1033 |
|
|
|
1034 |
|
|
// File operations
|
1035 |
|
|
static int ramfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
|
1036 |
|
|
static int ramfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
|
1037 |
|
|
static int ramfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
|
1038 |
|
|
static int ramfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
|
1039 |
|
|
CYG_ADDRWORD data);
|
1040 |
|
|
static int ramfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode );
|
1041 |
|
|
static int ramfs_fo_close (struct CYG_FILE_TAG *fp);
|
1042 |
|
|
static int ramfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );
|
1043 |
|
|
static int ramfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
|
1044 |
|
|
static int ramfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
|
1045 |
|
|
|
1046 |
|
|
// Directory operations
|
1047 |
|
|
static int ramfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
|
1048 |
|
|
static int ramfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
|
1049 |
|
|
|
1050 |
|
|
|
1051 |
|
|
|
1052 |
|
|
We define all of the fstab entries and all of the file IO
|
1053 |
|
|
operations. We also define alternatives for the
|
1054 |
|
|
fo_read and
|
1055 |
|
|
fo_lseek file IO operations.
|
1056 |
|
|
|
1057 |
|
|
|
1058 |
|
|
|
1059 |
|
|
We can now define the filesystem table entry. There is a macro,
|
1060 |
|
|
FSTAB_ENTRY to do this:
|
1061 |
|
|
|
1062 |
|
|
|
1063 |
|
|
|
1064 |
|
|
|
1065 |
|
|
//==========================================================================
|
1066 |
|
|
// Filesystem table entries
|
1067 |
|
|
|
1068 |
|
|
// -------------------------------------------------------------------------
|
1069 |
|
|
// Fstab entry.
|
1070 |
|
|
// This defines the entry in the filesystem table.
|
1071 |
|
|
// For simplicity we use _FILESYSTEM synchronization for all accesses since
|
1072 |
|
|
// we should never block in any filesystem operations.
|
1073 |
|
|
|
1074 |
|
|
FSTAB_ENTRY( ramfs_fste, "ramfs", 0,
|
1075 |
|
|
CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
|
1076 |
|
|
ramfs_mount,
|
1077 |
|
|
ramfs_umount,
|
1078 |
|
|
ramfs_open,
|
1079 |
|
|
ramfs_unlink,
|
1080 |
|
|
ramfs_mkdir,
|
1081 |
|
|
ramfs_rmdir,
|
1082 |
|
|
ramfs_rename,
|
1083 |
|
|
ramfs_link,
|
1084 |
|
|
ramfs_opendir,
|
1085 |
|
|
ramfs_chdir,
|
1086 |
|
|
ramfs_stat,
|
1087 |
|
|
ramfs_getinfo,
|
1088 |
|
|
ramfs_setinfo);
|
1089 |
|
|
|
1090 |
|
|
|
1091 |
|
|
|
1092 |
|
|
The first argument to this macro gives the fstab entry a name, the
|
1093 |
|
|
remainder are initializers for the field of the structure.
|
1094 |
|
|
|
1095 |
|
|
|
1096 |
|
|
|
1097 |
|
|
We must also define the file operations table that is installed in all
|
1098 |
|
|
open file table entries:
|
1099 |
|
|
|
1100 |
|
|
|
1101 |
|
|
|
1102 |
|
|
// -------------------------------------------------------------------------
|
1103 |
|
|
// File operations.
|
1104 |
|
|
// This set of file operations are used for normal open files.
|
1105 |
|
|
|
1106 |
|
|
static cyg_fileops ramfs_fileops =
|
1107 |
|
|
{
|
1108 |
|
|
ramfs_fo_read,
|
1109 |
|
|
ramfs_fo_write,
|
1110 |
|
|
ramfs_fo_lseek,
|
1111 |
|
|
ramfs_fo_ioctl,
|
1112 |
|
|
cyg_fileio_seltrue,
|
1113 |
|
|
ramfs_fo_fsync,
|
1114 |
|
|
ramfs_fo_close,
|
1115 |
|
|
ramfs_fo_fstat,
|
1116 |
|
|
ramfs_fo_getinfo,
|
1117 |
|
|
ramfs_fo_setinfo
|
1118 |
|
|
};
|
1119 |
|
|
|
1120 |
|
|
|
1121 |
|
|
|
1122 |
|
|
These all point to functions supplied by the filesystem except the
|
1123 |
|
|
fo_select field which is filled with a
|
1124 |
|
|
pointer to cyg_fileio_seltrue(). This is provided
|
1125 |
|
|
by the FILEIO package and is a select function that always returns
|
1126 |
|
|
true to all operations.
|
1127 |
|
|
|
1128 |
|
|
|
1129 |
|
|
|
1130 |
|
|
Finally, we need to define a set of file operations for use when
|
1131 |
|
|
reading directories. This table only defines the
|
1132 |
|
|
fo_read and
|
1133 |
|
|
fo_lseek operations. The rest are filled
|
1134 |
|
|
with stub functions supplied by the FILEIO package that just return an
|
1135 |
|
|
error code.
|
1136 |
|
|
|
1137 |
|
|
|
1138 |
|
|
|
1139 |
|
|
// -------------------------------------------------------------------------
|
1140 |
|
|
// Directory file operations.
|
1141 |
|
|
// This set of operations are used for open directories. Most entries
|
1142 |
|
|
// point to error-returning stub functions. Only the read, lseek and
|
1143 |
|
|
// close entries are functional.
|
1144 |
|
|
|
1145 |
|
|
static cyg_fileops ramfs_dirops =
|
1146 |
|
|
{
|
1147 |
|
|
ramfs_fo_dirread,
|
1148 |
|
|
(cyg_fileop_write *)cyg_fileio_enosys,
|
1149 |
|
|
ramfs_fo_dirlseek,
|
1150 |
|
|
(cyg_fileop_ioctl *)cyg_fileio_enosys,
|
1151 |
|
|
cyg_fileio_seltrue,
|
1152 |
|
|
(cyg_fileop_fsync *)cyg_fileio_enosys,
|
1153 |
|
|
ramfs_fo_close,
|
1154 |
|
|
(cyg_fileop_fstat *)cyg_fileio_enosys,
|
1155 |
|
|
(cyg_fileop_getinfo *)cyg_fileio_enosys,
|
1156 |
|
|
(cyg_fileop_setinfo *)cyg_fileio_enosys
|
1157 |
|
|
};
|
1158 |
|
|
|
1159 |
|
|
|
1160 |
|
|
|
1161 |
|
|
If the filesystem wants to have an instance automatically mounted on
|
1162 |
|
|
system startup, it must also define a mount table entry. This is done
|
1163 |
|
|
with the MTAB_ENTRY macro. This is an example from
|
1164 |
|
|
the test filesystem of how this is used:
|
1165 |
|
|
|
1166 |
|
|
|
1167 |
|
|
|
1168 |
|
|
MTAB_ENTRY( testfs_mte1,
|
1169 |
|
|
"/",
|
1170 |
|
|
"testfs",
|
1171 |
|
|
"",
|
1172 |
|
|
0);
|
1173 |
|
|
|
1174 |
|
|
|
1175 |
|
|
|
1176 |
|
|
The first argument provides a name for the table entry. The following
|
1177 |
|
|
arguments provide initialization for the
|
1178 |
|
|
name, fsname,
|
1179 |
|
|
devname and data
|
1180 |
|
|
fields respectively.
|
1181 |
|
|
|
1182 |
|
|
|
1183 |
|
|
|
1184 |
|
|
These definitions are adequate to let the new filesystem interact
|
1185 |
|
|
with the FILEIO package. The new filesystem now needs to be fleshed
|
1186 |
|
|
out with implementations of the functions defined above. Obviously,
|
1187 |
|
|
the exact form this takes will depend on what the filesystem is
|
1188 |
|
|
intended to do. Take a look at the RAM and ROM filesystems for
|
1189 |
|
|
examples of how this has been done.
|
1190 |
|
|
|
1191 |
|
|
|
1192 |
|
|
|
1193 |
|
|
|
1194 |
|
|
|
1195 |
|
|
|
1196 |
|
|
|