summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/exec/include/rtems/libio_.h248
-rw-r--r--c/src/exec/libcsupport/include/rtems/libio.h551
-rw-r--r--c/src/exec/libcsupport/include/rtems/libio_.h248
-rw-r--r--c/src/exec/libcsupport/src/CASES23
-rw-r--r--c/src/exec/libcsupport/src/TODO11
-rw-r--r--c/src/exec/libcsupport/src/__brk.c27
-rw-r--r--c/src/exec/libcsupport/src/__gettod.c19
-rw-r--r--c/src/exec/libcsupport/src/__sbrk.c29
-rw-r--r--c/src/exec/libcsupport/src/__times.c36
-rw-r--r--c/src/exec/libcsupport/src/access.c46
-rw-r--r--c/src/exec/libcsupport/src/base_fs.c81
-rw-r--r--c/src/exec/libcsupport/src/cfgetispeed.c29
-rw-r--r--c/src/exec/libcsupport/src/cfgetospeed.c29
-rw-r--r--c/src/exec/libcsupport/src/cfsetispeed.c36
-rw-r--r--c/src/exec/libcsupport/src/cfsetospeed.c36
-rw-r--r--c/src/exec/libcsupport/src/chdir.c50
-rw-r--r--c/src/exec/libcsupport/src/chmod.c40
-rw-r--r--c/src/exec/libcsupport/src/chown.c38
-rw-r--r--c/src/exec/libcsupport/src/close.c70
-rw-r--r--c/src/exec/libcsupport/src/closedir.c62
-rw-r--r--c/src/exec/libcsupport/src/dup.c23
-rw-r--r--c/src/exec/libcsupport/src/dup2.c49
-rw-r--r--c/src/exec/libcsupport/src/eval.c74
-rw-r--r--c/src/exec/libcsupport/src/fchmod.c50
-rw-r--r--c/src/exec/libcsupport/src/fcntl.c111
-rw-r--r--c/src/exec/libcsupport/src/fdatasync.c45
-rw-r--r--c/src/exec/libcsupport/src/fpathconf.c91
-rw-r--r--c/src/exec/libcsupport/src/fstat.c94
-rw-r--r--c/src/exec/libcsupport/src/fsync.c45
-rw-r--r--c/src/exec/libcsupport/src/ftruncate.c60
-rw-r--r--c/src/exec/libcsupport/src/getdents.c55
-rw-r--r--c/src/exec/libcsupport/src/hosterr.c27
-rw-r--r--c/src/exec/libcsupport/src/ioctl.c57
-rw-r--r--c/src/exec/libcsupport/src/libio.c663
-rw-r--r--c/src/exec/libcsupport/src/link.c60
-rw-r--r--c/src/exec/libcsupport/src/lseek.c93
-rw-r--r--c/src/exec/libcsupport/src/malloc.c14
-rw-r--r--c/src/exec/libcsupport/src/mkdir.c28
-rw-r--r--c/src/exec/libcsupport/src/mkfifo.c25
-rw-r--r--c/src/exec/libcsupport/src/mknod.c60
-rw-r--r--c/src/exec/libcsupport/src/mount.c299
-rw-r--r--c/src/exec/libcsupport/src/newlibc.c78
-rw-r--r--c/src/exec/libcsupport/src/no_libc.c20
-rw-r--r--c/src/exec/libcsupport/src/open.c202
-rw-r--r--c/src/exec/libcsupport/src/opendir.c78
-rw-r--r--c/src/exec/libcsupport/src/pathconf.c38
-rw-r--r--c/src/exec/libcsupport/src/pipe.c (renamed from c/src/lib/libc/_execve.c)14
-rw-r--r--c/src/exec/libcsupport/src/read.c84
-rw-r--r--c/src/exec/libcsupport/src/readdir.c75
-rw-r--r--c/src/exec/libcsupport/src/readlink.c43
-rw-r--r--c/src/exec/libcsupport/src/rewinddir.c21
-rw-r--r--c/src/exec/libcsupport/src/rmdir.c56
-rw-r--r--c/src/exec/libcsupport/src/scandir.c148
-rw-r--r--c/src/exec/libcsupport/src/seekdir.c27
-rw-r--r--c/src/exec/libcsupport/src/stat.c79
-rw-r--r--c/src/exec/libcsupport/src/symlink.c34
-rw-r--r--c/src/exec/libcsupport/src/tcdrain.c21
-rw-r--r--c/src/exec/libcsupport/src/tcgetattr.c33
-rw-r--r--c/src/exec/libcsupport/src/tcsetattr.c38
-rw-r--r--c/src/exec/libcsupport/src/telldir.c28
-rw-r--r--c/src/exec/libcsupport/src/truncate.c41
-rw-r--r--c/src/exec/libcsupport/src/umask.c30
-rw-r--r--c/src/exec/libcsupport/src/unixlibc.c10
-rw-r--r--c/src/exec/libcsupport/src/unlink.c44
-rw-r--r--c/src/exec/libcsupport/src/unmount.c214
-rw-r--r--c/src/exec/libcsupport/src/utime.c35
-rw-r--r--c/src/exec/libcsupport/src/write.c92
-rw-r--r--c/src/exec/libfs/src/imfs/deviceio.c215
-rw-r--r--c/src/exec/libfs/src/imfs/imfs.h445
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_chown.c52
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_creat.c130
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_debug.c160
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_directory.c278
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_eval.c638
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_fchmod.c55
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_free.c99
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_getchild.c68
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_gtkn.c84
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_init.c158
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_initsupp.c158
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_link.c72
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_mknod.c76
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_mount.c49
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_ntype.c29
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_readlink.c40
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_rmnod.c97
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_stat.c59
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_symlink.c60
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_unlink.c67
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_unmount.c58
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_utime.c38
-rw-r--r--c/src/exec/libfs/src/imfs/ioman.c83
-rw-r--r--c/src/exec/libfs/src/imfs/memfile.c1000
-rw-r--r--c/src/exec/posix/include/sys/Makefile.in2
-rw-r--r--c/src/exec/posix/src/getpid.c19
-rw-r--r--c/src/exec/posix/src/psignal.c20
-rw-r--r--c/src/exec/posix/sys/Makefile.in2
-rw-r--r--c/src/exec/sapi/src/io.c4
-rw-r--r--c/src/lib/include/rtems/libio.h551
-rw-r--r--c/src/lib/include/rtems/libio_.h248
-rw-r--r--c/src/lib/libbsp/shared/bsplibc.c2
-rw-r--r--c/src/lib/libbsp/shared/bsppost.c6
-rw-r--r--c/src/lib/libc/CASES23
-rw-r--r--c/src/lib/libc/Makefile.in51
-rw-r--r--c/src/lib/libc/TODO11
-rw-r--r--c/src/lib/libc/__brk.c27
-rw-r--r--c/src/lib/libc/__gettod.c19
-rw-r--r--c/src/lib/libc/__sbrk.c29
-rw-r--r--c/src/lib/libc/__times.c36
-rw-r--r--c/src/lib/libc/access.c46
-rw-r--r--c/src/lib/libc/base_fs.c81
-rw-r--r--c/src/lib/libc/cfgetispeed.c29
-rw-r--r--c/src/lib/libc/cfgetospeed.c29
-rw-r--r--c/src/lib/libc/cfiospeed.c54
-rw-r--r--c/src/lib/libc/cfsetispeed.c36
-rw-r--r--c/src/lib/libc/cfsetospeed.c36
-rw-r--r--c/src/lib/libc/chdir.c50
-rw-r--r--c/src/lib/libc/chmod.c40
-rw-r--r--c/src/lib/libc/chown.c38
-rw-r--r--c/src/lib/libc/close.c70
-rw-r--r--c/src/lib/libc/closedir.c62
-rw-r--r--c/src/lib/libc/deviceio.c215
-rw-r--r--c/src/lib/libc/dup.c23
-rw-r--r--c/src/lib/libc/dup2.c49
-rw-r--r--c/src/lib/libc/eval.c74
-rw-r--r--c/src/lib/libc/fchmod.c50
-rw-r--r--c/src/lib/libc/fcntl.c111
-rw-r--r--c/src/lib/libc/fdatasync.c45
-rw-r--r--c/src/lib/libc/fpathconf.c91
-rw-r--r--c/src/lib/libc/fstat.c94
-rw-r--r--c/src/lib/libc/fsync.c45
-rw-r--r--c/src/lib/libc/ftruncate.c60
-rw-r--r--c/src/lib/libc/getdents.c55
-rw-r--r--c/src/lib/libc/hosterr.c27
-rw-r--r--c/src/lib/libc/imfs.h445
-rw-r--r--c/src/lib/libc/imfs_chown.c52
-rw-r--r--c/src/lib/libc/imfs_creat.c130
-rw-r--r--c/src/lib/libc/imfs_debug.c160
-rw-r--r--c/src/lib/libc/imfs_directory.c278
-rw-r--r--c/src/lib/libc/imfs_eval.c638
-rw-r--r--c/src/lib/libc/imfs_fchmod.c55
-rw-r--r--c/src/lib/libc/imfs_free.c99
-rw-r--r--c/src/lib/libc/imfs_getchild.c68
-rw-r--r--c/src/lib/libc/imfs_gtkn.c84
-rw-r--r--c/src/lib/libc/imfs_handlers.c93
-rw-r--r--c/src/lib/libc/imfs_init.c158
-rw-r--r--c/src/lib/libc/imfs_initsupp.c158
-rw-r--r--c/src/lib/libc/imfs_link.c72
-rw-r--r--c/src/lib/libc/imfs_mknod.c76
-rw-r--r--c/src/lib/libc/imfs_mount.c49
-rw-r--r--c/src/lib/libc/imfs_ntype.c29
-rw-r--r--c/src/lib/libc/imfs_readlink.c40
-rw-r--r--c/src/lib/libc/imfs_rmnod.c97
-rw-r--r--c/src/lib/libc/imfs_stat.c59
-rw-r--r--c/src/lib/libc/imfs_symlink.c60
-rw-r--r--c/src/lib/libc/imfs_unlink.c67
-rw-r--r--c/src/lib/libc/imfs_unmount.c58
-rw-r--r--c/src/lib/libc/imfs_utime.c38
-rw-r--r--c/src/lib/libc/internal.h41
-rw-r--r--c/src/lib/libc/ioctl.c57
-rw-r--r--c/src/lib/libc/ioman.c83
-rw-r--r--c/src/lib/libc/libio.c663
-rw-r--r--c/src/lib/libc/libio.h551
-rw-r--r--c/src/lib/libc/libio_.h248
-rw-r--r--c/src/lib/libc/link.c60
-rw-r--r--c/src/lib/libc/lseek.c93
-rw-r--r--c/src/lib/libc/malloc.c14
-rw-r--r--c/src/lib/libc/memfile.c1000
-rw-r--r--c/src/lib/libc/mkdir.c28
-rw-r--r--c/src/lib/libc/mkfifo.c25
-rw-r--r--c/src/lib/libc/mknod.c60
-rw-r--r--c/src/lib/libc/mount.c299
-rw-r--r--c/src/lib/libc/newlibc.c78
-rw-r--r--c/src/lib/libc/newlibif.c93
-rw-r--r--c/src/lib/libc/newlibifr.c103
-rw-r--r--c/src/lib/libc/no_libc.c20
-rw-r--r--c/src/lib/libc/open.c202
-rw-r--r--c/src/lib/libc/opendir.c78
-rw-r--r--c/src/lib/libc/pathconf.c38
-rw-r--r--c/src/lib/libc/pipe.c23
-rw-r--r--c/src/lib/libc/read.c84
-rw-r--r--c/src/lib/libc/readdir.c75
-rw-r--r--c/src/lib/libc/readlink.c43
-rw-r--r--c/src/lib/libc/rewinddir.c21
-rw-r--r--c/src/lib/libc/rmdir.c56
-rw-r--r--c/src/lib/libc/scandir.c148
-rw-r--r--c/src/lib/libc/seekdir.c27
-rw-r--r--c/src/lib/libc/stat.c79
-rw-r--r--c/src/lib/libc/support.c52
-rw-r--r--c/src/lib/libc/symlink.c34
-rw-r--r--c/src/lib/libc/syscalls.c99
-rw-r--r--c/src/lib/libc/tcattr.c40
-rw-r--r--c/src/lib/libc/tcdrain.c21
-rw-r--r--c/src/lib/libc/tcgetattr.c33
-rw-r--r--c/src/lib/libc/tcsetattr.c38
-rw-r--r--c/src/lib/libc/telldir.c28
-rw-r--r--c/src/lib/libc/truncate.c41
-rw-r--r--c/src/lib/libc/umask.c30
-rw-r--r--c/src/lib/libc/unixlibc.c10
-rw-r--r--c/src/lib/libc/unlink.c44
-rw-r--r--c/src/lib/libc/unmount.c214
-rw-r--r--c/src/lib/libc/utime.c35
-rw-r--r--c/src/lib/libc/write.c92
-rw-r--r--c/src/lib/libchip/serial/ns16550.c1
-rw-r--r--c/src/libchip/serial/ns16550.c1
-rw-r--r--c/src/libfs/src/imfs/deviceio.c215
-rw-r--r--c/src/libfs/src/imfs/imfs.h445
-rw-r--r--c/src/libfs/src/imfs/imfs_chown.c52
-rw-r--r--c/src/libfs/src/imfs/imfs_creat.c130
-rw-r--r--c/src/libfs/src/imfs/imfs_debug.c160
-rw-r--r--c/src/libfs/src/imfs/imfs_directory.c278
-rw-r--r--c/src/libfs/src/imfs/imfs_eval.c638
-rw-r--r--c/src/libfs/src/imfs/imfs_fchmod.c55
-rw-r--r--c/src/libfs/src/imfs/imfs_free.c99
-rw-r--r--c/src/libfs/src/imfs/imfs_getchild.c68
-rw-r--r--c/src/libfs/src/imfs/imfs_gtkn.c84
-rw-r--r--c/src/libfs/src/imfs/imfs_init.c158
-rw-r--r--c/src/libfs/src/imfs/imfs_initsupp.c158
-rw-r--r--c/src/libfs/src/imfs/imfs_link.c72
-rw-r--r--c/src/libfs/src/imfs/imfs_mknod.c76
-rw-r--r--c/src/libfs/src/imfs/imfs_mount.c49
-rw-r--r--c/src/libfs/src/imfs/imfs_ntype.c29
-rw-r--r--c/src/libfs/src/imfs/imfs_readlink.c40
-rw-r--r--c/src/libfs/src/imfs/imfs_rmnod.c97
-rw-r--r--c/src/libfs/src/imfs/imfs_stat.c59
-rw-r--r--c/src/libfs/src/imfs/imfs_symlink.c60
-rw-r--r--c/src/libfs/src/imfs/imfs_unlink.c67
-rw-r--r--c/src/libfs/src/imfs/imfs_unmount.c58
-rw-r--r--c/src/libfs/src/imfs/imfs_utime.c38
-rw-r--r--c/src/libfs/src/imfs/ioman.c83
-rw-r--r--c/src/libfs/src/imfs/memfile.c1000
-rw-r--r--c/src/tests/sptests/spsize/size.c22
-rw-r--r--configure18
-rw-r--r--cpukit/include/rtems/libio_.h248
-rw-r--r--cpukit/libcsupport/include/rtems/libio.h551
-rw-r--r--cpukit/libcsupport/include/rtems/libio_.h248
-rw-r--r--cpukit/libcsupport/src/CASES23
-rw-r--r--cpukit/libcsupport/src/TODO11
-rw-r--r--cpukit/libcsupport/src/__brk.c27
-rw-r--r--cpukit/libcsupport/src/__gettod.c19
-rw-r--r--cpukit/libcsupport/src/__sbrk.c29
-rw-r--r--cpukit/libcsupport/src/__times.c36
-rw-r--r--cpukit/libcsupport/src/access.c46
-rw-r--r--cpukit/libcsupport/src/base_fs.c81
-rw-r--r--cpukit/libcsupport/src/cfgetispeed.c29
-rw-r--r--cpukit/libcsupport/src/cfgetospeed.c29
-rw-r--r--cpukit/libcsupport/src/cfsetispeed.c36
-rw-r--r--cpukit/libcsupport/src/cfsetospeed.c36
-rw-r--r--cpukit/libcsupport/src/chdir.c50
-rw-r--r--cpukit/libcsupport/src/chmod.c40
-rw-r--r--cpukit/libcsupport/src/chown.c38
-rw-r--r--cpukit/libcsupport/src/close.c70
-rw-r--r--cpukit/libcsupport/src/closedir.c62
-rw-r--r--cpukit/libcsupport/src/dup.c23
-rw-r--r--cpukit/libcsupport/src/dup2.c49
-rw-r--r--cpukit/libcsupport/src/eval.c74
-rw-r--r--cpukit/libcsupport/src/fchmod.c50
-rw-r--r--cpukit/libcsupport/src/fcntl.c111
-rw-r--r--cpukit/libcsupport/src/fdatasync.c45
-rw-r--r--cpukit/libcsupport/src/fpathconf.c91
-rw-r--r--cpukit/libcsupport/src/fstat.c94
-rw-r--r--cpukit/libcsupport/src/fsync.c45
-rw-r--r--cpukit/libcsupport/src/ftruncate.c60
-rw-r--r--cpukit/libcsupport/src/getdents.c55
-rw-r--r--cpukit/libcsupport/src/hosterr.c27
-rw-r--r--cpukit/libcsupport/src/ioctl.c57
-rw-r--r--cpukit/libcsupport/src/libio.c663
-rw-r--r--cpukit/libcsupport/src/link.c60
-rw-r--r--cpukit/libcsupport/src/lseek.c93
-rw-r--r--cpukit/libcsupport/src/malloc.c14
-rw-r--r--cpukit/libcsupport/src/mkdir.c28
-rw-r--r--cpukit/libcsupport/src/mkfifo.c25
-rw-r--r--cpukit/libcsupport/src/mknod.c60
-rw-r--r--cpukit/libcsupport/src/mount.c299
-rw-r--r--cpukit/libcsupport/src/newlibc.c78
-rw-r--r--cpukit/libcsupport/src/no_libc.c20
-rw-r--r--cpukit/libcsupport/src/open.c202
-rw-r--r--cpukit/libcsupport/src/opendir.c78
-rw-r--r--cpukit/libcsupport/src/pathconf.c38
-rw-r--r--cpukit/libcsupport/src/pipe.c23
-rw-r--r--cpukit/libcsupport/src/read.c84
-rw-r--r--cpukit/libcsupport/src/readdir.c75
-rw-r--r--cpukit/libcsupport/src/readlink.c43
-rw-r--r--cpukit/libcsupport/src/rewinddir.c21
-rw-r--r--cpukit/libcsupport/src/rmdir.c56
-rw-r--r--cpukit/libcsupport/src/scandir.c148
-rw-r--r--cpukit/libcsupport/src/seekdir.c27
-rw-r--r--cpukit/libcsupport/src/stat.c79
-rw-r--r--cpukit/libcsupport/src/symlink.c34
-rw-r--r--cpukit/libcsupport/src/tcdrain.c21
-rw-r--r--cpukit/libcsupport/src/tcgetattr.c33
-rw-r--r--cpukit/libcsupport/src/tcsetattr.c38
-rw-r--r--cpukit/libcsupport/src/telldir.c28
-rw-r--r--cpukit/libcsupport/src/truncate.c41
-rw-r--r--cpukit/libcsupport/src/umask.c30
-rw-r--r--cpukit/libcsupport/src/unixlibc.c10
-rw-r--r--cpukit/libcsupport/src/unlink.c44
-rw-r--r--cpukit/libcsupport/src/unmount.c214
-rw-r--r--cpukit/libcsupport/src/utime.c35
-rw-r--r--cpukit/libcsupport/src/write.c92
-rw-r--r--cpukit/libfs/src/imfs/deviceio.c215
-rw-r--r--cpukit/libfs/src/imfs/imfs.h445
-rw-r--r--cpukit/libfs/src/imfs/imfs_chown.c52
-rw-r--r--cpukit/libfs/src/imfs/imfs_creat.c130
-rw-r--r--cpukit/libfs/src/imfs/imfs_debug.c160
-rw-r--r--cpukit/libfs/src/imfs/imfs_directory.c278
-rw-r--r--cpukit/libfs/src/imfs/imfs_eval.c638
-rw-r--r--cpukit/libfs/src/imfs/imfs_fchmod.c55
-rw-r--r--cpukit/libfs/src/imfs/imfs_free.c99
-rw-r--r--cpukit/libfs/src/imfs/imfs_getchild.c68
-rw-r--r--cpukit/libfs/src/imfs/imfs_gtkn.c84
-rw-r--r--cpukit/libfs/src/imfs/imfs_init.c158
-rw-r--r--cpukit/libfs/src/imfs/imfs_initsupp.c158
-rw-r--r--cpukit/libfs/src/imfs/imfs_link.c72
-rw-r--r--cpukit/libfs/src/imfs/imfs_mknod.c76
-rw-r--r--cpukit/libfs/src/imfs/imfs_mount.c49
-rw-r--r--cpukit/libfs/src/imfs/imfs_ntype.c29
-rw-r--r--cpukit/libfs/src/imfs/imfs_readlink.c40
-rw-r--r--cpukit/libfs/src/imfs/imfs_rmnod.c97
-rw-r--r--cpukit/libfs/src/imfs/imfs_stat.c59
-rw-r--r--cpukit/libfs/src/imfs/imfs_symlink.c60
-rw-r--r--cpukit/libfs/src/imfs/imfs_unlink.c67
-rw-r--r--cpukit/libfs/src/imfs/imfs_unmount.c58
-rw-r--r--cpukit/libfs/src/imfs/imfs_utime.c38
-rw-r--r--cpukit/libfs/src/imfs/ioman.c83
-rw-r--r--cpukit/libfs/src/imfs/memfile.c1000
-rw-r--r--cpukit/posix/src/getpid.c19
-rw-r--r--cpukit/posix/src/psignal.c20
-rw-r--r--cpukit/sapi/src/io.c4
-rw-r--r--testsuites/sptests/spsize/size.c22
330 files changed, 31856 insertions, 2518 deletions
diff --git a/c/src/exec/include/rtems/libio_.h b/c/src/exec/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/exec/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/exec/libcsupport/include/rtems/libio.h b/c/src/exec/libcsupport/include/rtems/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/exec/libcsupport/include/rtems/libio.h
+++ b/c/src/exec/libcsupport/include/rtems/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/exec/libcsupport/include/rtems/libio_.h b/c/src/exec/libcsupport/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/exec/libcsupport/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/exec/libcsupport/src/CASES b/c/src/exec/libcsupport/src/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/c/src/exec/libcsupport/src/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/c/src/exec/libcsupport/src/TODO b/c/src/exec/libcsupport/src/TODO
new file mode 100644
index 0000000000..9d894688d9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/TODO
@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
diff --git a/c/src/exec/libcsupport/src/__brk.c b/c/src/exec/libcsupport/src/__brk.c
index 4dab22c729..24efa93adb 100644
--- a/c/src/exec/libcsupport/src/__brk.c
+++ b/c/src/exec/libcsupport/src/__brk.c
@@ -1,10 +1,7 @@
-#if !defined(RTEMS_UNIX)
-
/*
- * RTEMS "Broken" __brk/__sbrk Implementation
- *
- * NOTE: sbrk is BSP provided.
+ * RTEMS "Broken" __brk Implementation
*
+ * NOTE: sbrk() is provided by each BSP.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,27 +15,15 @@
*/
#include <rtems.h>
+#if !defined(RTEMS_UNIX)
-#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#ifdef RTEMS_NEWLIB
-#include <reent.h>
-#endif
-#include <unistd.h>
-
-/* we use RTEMS for memory management. We don't need sbrk */
-void * __sbrk(int incr)
-{
- errno = EINVAL;
- return (void *)0;
-}
-
-int __brk( const void *endds )
+int __brk(
+ const void *endds
+)
{
errno = EINVAL;
return -1;
}
-
#endif
diff --git a/c/src/exec/libcsupport/src/__gettod.c b/c/src/exec/libcsupport/src/__gettod.c
index dc83c47ce4..16857da870 100644
--- a/c/src/exec/libcsupport/src/__gettod.c
+++ b/c/src/exec/libcsupport/src/__gettod.c
@@ -1,11 +1,5 @@
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-
-#include <rtems.h>
-
-#if !defined(RTEMS_UNIX)
/*
- * RTEMS gettimeofday Implementation
- *
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,6 +12,11 @@
* $Id$
*/
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
#ifdef RTEMS_NEWLIB
#include <sys/reent.h>
#endif
@@ -61,7 +60,7 @@ int gettimeofday(
*
* NOTE: XXX this routine should really be in the executive proper.
*/
-
+
rtems_interrupt_disable(level);
seconds = _TOD_Seconds_since_epoch;
microseconds = _TOD_Current.ticks;
@@ -86,7 +85,7 @@ int gettimeofday(
return 0;
}
-#if defined(RTEMS_NEWLIB)
+#if defined(RTEMS_NEWLIB)
/*
* "Reentrant" version
@@ -102,7 +101,7 @@ int _gettimeofday_r(
}
/*
- * "System call" version
+ * "System call" version
*/
int _gettimeofday(
diff --git a/c/src/exec/libcsupport/src/__sbrk.c b/c/src/exec/libcsupport/src/__sbrk.c
new file mode 100644
index 0000000000..b1d31467fd
--- /dev/null
+++ b/c/src/exec/libcsupport/src/__sbrk.c
@@ -0,0 +1,29 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/__times.c b/c/src/exec/libcsupport/src/__times.c
index 635bf8e062..5f7525ec5f 100644
--- a/c/src/exec/libcsupport/src/__times.c
+++ b/c/src/exec/libcsupport/src/__times.c
@@ -1,6 +1,5 @@
/*
- * RTEMS _times Implementation
- *
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -25,8 +24,8 @@ clock_t _times(
struct tms *ptms
)
{
- rtems_status_code status;
- rtems_interval ticks_since_boot;
+ rtems_status_code status;
+ rtems_interval ticks;
if ( !ptms ) {
errno = EFAULT;
@@ -34,21 +33,19 @@ clock_t _times(
}
/* "POSIX" does not seem to allow for not having a TOD */
- status = rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &ticks_since_boot
- );
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
if ( status != RTEMS_SUCCESSFUL ) {
assert( 0 );
return -1;
}
/*
- * RTEMS has no notion of system versus user time and does
- * not (as of 3.2.0) keep track of CPU usage on a per task basis.
+ * RTEMS has no notion of system versus user time and although
+ * a way to keep track of per task CPU usage was added since
+ * 3.6.0, this routine does not utilize it yet.
*/
- ptms->tms_utime = ticks_since_boot;
+ ptms->tms_utime = ticks;
ptms->tms_stime = 0;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
@@ -56,6 +53,12 @@ clock_t _times(
return 0;
}
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
clock_t times(
struct tms *ptms
)
@@ -63,12 +66,21 @@ clock_t times(
return _times( ptms );
}
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
clock_t _times_r(
struct _reent *ptr,
struct tms *ptms
)
{
- return _times(ptms);
+ return _times( ptms );
}
#endif
diff --git a/c/src/exec/libcsupport/src/access.c b/c/src/exec/libcsupport/src/access.c
new file mode 100644
index 0000000000..a8be44a9a3
--- /dev/null
+++ b/c/src/exec/libcsupport/src/access.c
@@ -0,0 +1,46 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/c/src/exec/libcsupport/src/base_fs.c b/c/src/exec/libcsupport/src/base_fs.c
new file mode 100644
index 0000000000..c8c23e5b43
--- /dev/null
+++ b/c/src/exec/libcsupport/src/base_fs.c
@@ -0,0 +1,81 @@
+/*
+ * Base file system initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_filesystem_location_info_t rtems_filesystem_current;
+rtems_filesystem_location_info_t rtems_filesystem_root;
+nlink_t rtems_filesystem_link_counts;
+
+/*
+ * Default mode for created files.
+ */
+
+mode_t rtems_filesystem_umask;
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system with one instantiation
+ * of the IMFS with a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *first_entry;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = S_IWOTH | S_IROTH;
+
+ init_fs_mount_table();
+
+ status = mount(
+ &first_entry,
+ &IMFS_ops,
+ "RW",
+ NULL,
+ NULL );
+ if( status == -1 ){
+ rtems_fatal_error_occurred( 0xABCD0002 );
+ }
+
+ rtems_filesystem_link_counts = 0;
+
+ rtems_filesystem_root = first_entry->mt_fs_root;
+
+ rtems_filesystem_current = rtems_filesystem_root;
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+}
diff --git a/c/src/exec/libcsupport/src/cfgetispeed.c b/c/src/exec/libcsupport/src/cfgetispeed.c
new file mode 100644
index 0000000000..61d97cb2f1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfgetispeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfgetospeed.c b/c/src/exec/libcsupport/src/cfgetospeed.c
new file mode 100644
index 0000000000..8815d436e9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfgetospeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfsetispeed.c b/c/src/exec/libcsupport/src/cfsetispeed.c
new file mode 100644
index 0000000000..37d3cd0584
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfsetispeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfsetospeed.c b/c/src/exec/libcsupport/src/cfsetospeed.c
new file mode 100644
index 0000000000..f01237103b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfsetospeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/chdir.c b/c/src/exec/libcsupport/src/chdir.c
new file mode 100644
index 0000000000..4acbc8cfe0
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chdir.c
@@ -0,0 +1,50 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/c/src/exec/libcsupport/src/chmod.c b/c/src/exec/libcsupport/src/chmod.c
new file mode 100644
index 0000000000..fa57d50691
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chmod.c
@@ -0,0 +1,40 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "libio_.h"
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.handlers->fchmod)( &loc, mode );
+}
diff --git a/c/src/exec/libcsupport/src/chown.c b/c/src/exec/libcsupport/src/chown.c
new file mode 100644
index 0000000000..189096dcd1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chown.c
@@ -0,0 +1,38 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "libio_.h"
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->chown )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->chown)( &temp_loc, owner, group );
+}
diff --git a/c/src/exec/libcsupport/src/close.c b/c/src/exec/libcsupport/src/close.c
new file mode 100644
index 0000000000..94ddb45c90
--- /dev/null
+++ b/c/src/exec/libcsupport/src/close.c
@@ -0,0 +1,70 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+ int status;
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ int (*fp)(int fd);
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+ status = (*fp)( fd );
+ return status;
+ }
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+
+ if ( !iop->handlers )
+ set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->close )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->close)( iop );
+
+ rtems_libio_free( iop );
+
+ if (rc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( rc );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/closedir.c b/c/src/exec/libcsupport/src/closedir.c
index 5edb3499e6..4d948ec95b 100644
--- a/c/src/exec/libcsupport/src/closedir.c
+++ b/c/src/exec/libcsupport/src/closedir.c
@@ -1,9 +1,44 @@
/*
* closedir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <dirent.h>
@@ -11,10 +46,25 @@
#include <unistd.h>
#include <errno.h>
-int closedir(
- register DIR *dirp
-)
+
+#include "libio_.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
{
- errno = ENOSYS;
- return -1;
+ int fd;
+
+ if ( !dirp )
+ set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
}
diff --git a/c/src/exec/libcsupport/src/dup.c b/c/src/exec/libcsupport/src/dup.c
new file mode 100644
index 0000000000..c17db588a7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/dup.c
@@ -0,0 +1,23 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/c/src/exec/libcsupport/src/dup2.c b/c/src/exec/libcsupport/src/dup2.c
new file mode 100644
index 0000000000..5653425708
--- /dev/null
+++ b/c/src/exec/libcsupport/src/dup2.c
@@ -0,0 +1,49 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "libio_.h"
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/c/src/exec/libcsupport/src/eval.c b/c/src/exec/libcsupport/src/eval.c
new file mode 100644
index 0000000000..bf7dd1c126
--- /dev/null
+++ b/c/src/exec/libcsupport/src/eval.c
@@ -0,0 +1,74 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include "libio_.h"
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( follow_link ) {
+
+ if ( !pathloc->ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ type = (*pathloc->ops->node_type)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->eval_link)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
diff --git a/c/src/exec/libcsupport/src/fchmod.c b/c/src/exec/libcsupport/src/fchmod.c
new file mode 100644
index 0000000000..a3ca4507ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "libio_.h"
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fchmod().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode );
+}
+
diff --git a/c/src/exec/libcsupport/src/fcntl.c b/c/src/exec/libcsupport/src/fcntl.c
new file mode 100644
index 0000000000..f6f33534ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fcntl.c
@@ -0,0 +1,111 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include "libio_.h"
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ va_list ap;
+ rtems_libio_t *iop;
+
+ va_start( ap, cmd );
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fcntl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ /*
+ * This is how it appears that this case should work:
+ *
+ * filedes2 = va_arg( ap, int )
+ * if filedes2 is 0
+ * duplicate fd into a new descriptor
+ * else
+ * duplicate fd into specified descriptor after error checking it
+ *
+ * See dup2() in case we can eliminate stuff in there.
+ */
+ return -1;
+
+ case F_GETFD: /* get f_flags */
+ if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
+ return 1;
+ return 0;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ return 0;
+
+ case F_GETFL: /* more flags (cloexec) */
+ return -1;
+
+ case F_SETFL:
+ return -1;
+
+ case F_GETLK:
+ return -1;
+
+ case F_SETLK:
+ return -1;
+
+ case F_SETLKW:
+ return -1;
+
+ case F_SETOWN: /* for sockets. */
+ return -1;
+
+ case F_GETOWN: /* for sockets. */
+ return -1;
+
+ default:
+ break;
+ }
+ return -1;
+}
diff --git a/c/src/exec/libcsupport/src/fdatasync.c b/c/src/exec/libcsupport/src/fdatasync.c
new file mode 100644
index 0000000000..58a4c4e118
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fdatasync.c
@@ -0,0 +1,45 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fdatasync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync)( iop );
+}
diff --git a/c/src/exec/libcsupport/src/fpathconf.c b/c/src/exec/libcsupport/src/fpathconf.c
new file mode 100644
index 0000000000..ea2377e15b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fpathconf.c
@@ -0,0 +1,91 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then it is an error since fpathconf() is not included in the
+ * set.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the information request.
+ */
+
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/c/src/exec/libcsupport/src/fstat.c b/c/src/exec/libcsupport/src/fstat.c
new file mode 100644
index 0000000000..82d144dd2c
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fstat.c
@@ -0,0 +1,94 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "libio_.h"
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if (rtems_file_descriptor_type(fd)) {
+ switch (rtems_file_descriptor_type (fd)) {
+ case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
+ break;
+
+ case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
+#if !defined(__GO32__)
+ sbuf->st_mode = S_IFSOCK;
+ break;
+#endif
+
+ default:
+ set_errno_and_return_minus_one( EBADF );
+ }
+ }
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fstat)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/fsync.c b/c/src/exec/libcsupport/src/fsync.c
new file mode 100644
index 0000000000..a5ed1e99e7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fsync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fsync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync)( iop );
+}
diff --git a/c/src/exec/libcsupport/src/ftruncate.c b/c/src/exec/libcsupport/src/ftruncate.c
new file mode 100644
index 0000000000..7fb2286531
--- /dev/null
+++ b/c/src/exec/libcsupport/src/ftruncate.c
@@ -0,0 +1,60 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate)( iop, length );
+}
+
diff --git a/c/src/exec/libcsupport/src/getdents.c b/c/src/exec/libcsupport/src/getdents.c
index 9b16d82409..91631843b7 100644
--- a/c/src/exec/libcsupport/src/getdents.c
+++ b/c/src/exec/libcsupport/src/getdents.c
@@ -1,14 +1,59 @@
/*
- * Just enough to make newlib return an error.
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
+#include <errno.h>
+
+#include "libio_.h"
+
int getdents(
- int fd,
- void *buf,
- int len
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
)
{
- return -1;
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read)( iop, dd_buf, dd_len );
}
diff --git a/c/src/exec/libcsupport/src/hosterr.c b/c/src/exec/libcsupport/src/hosterr.c
index a55e4a7e84..6c0308df3b 100644
--- a/c/src/exec/libcsupport/src/hosterr.c
+++ b/c/src/exec/libcsupport/src/hosterr.c
@@ -13,31 +13,36 @@
*/
#include <rtems.h>
+#if defined(RTEMS_UNIX)
#include <errno.h>
-int host_errno(void);
+int host_errno( void );
/*
- * copy host errno, if any to thread aware errno, if any
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
*/
-void fix_syscall_errno(void)
+void fix_syscall_errno( void )
{
- errno = host_errno();
+ errno = host_errno();
}
/*
- * Get the host system errno, if any
- * When using newlib (or possibly other libc's) on top of UNIX
- * the errno returned by system calls may be unavailable due
- * to trickery of making errno thread aware.
- * This provides a kludge of getting at it.
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
*/
#undef errno
extern int errno;
int host_errno(void)
{
- return errno;
+ return errno;
}
-
+#endif
diff --git a/c/src/exec/libcsupport/src/ioctl.c b/c/src/exec/libcsupport/src/ioctl.c
new file mode 100644
index 0000000000..0aaf0379ae
--- /dev/null
+++ b/c/src/exec/libcsupport/src/ioctl.c
@@ -0,0 +1,57 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int ioctl(
+ int fd,
+ unsigned32 command,
+ void * buffer
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_ioctl_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, command, buffer );
+ }
+
+ /*
+ * Now process the ioctl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->ioctl )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/c/src/exec/libcsupport/src/libio.c b/c/src/exec/libcsupport/src/libio.c
index 12682c1190..e63a4626d4 100644
--- a/c/src/exec/libcsupport/src/libio.c
+++ b/c/src/exec/libcsupport/src/libio.c
@@ -1,524 +1,295 @@
/*
- * Provide UNIX/POSIX-like io system calls for RTEMS using the
- * RTEMS IO manager
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the low level
+ * POSIX system calls like open(), read, fstat(), etc.
+ *
+ * This provides the foundation for POSIX compliant IO system calls
+ * for RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
-#include <rtems.h>
-#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
-
-#include <stdio.h> /* O_RDONLY, et.al. */
-#include <fcntl.h> /* O_RDONLY, et.al. */
-#include <assert.h>
-
-#if ! defined(O_NDELAY)
-# if defined(solaris2)
-# define O_NDELAY O_NONBLOCK
-# elif defined(RTEMS_NEWLIB)
-# define O_NDELAY _FNBIO
-# endif
-#endif
-
-
-#include <errno.h>
-#include <string.h> /* strcmp */
-#include <unistd.h>
-#include <stdlib.h> /* calloc() */
-
-#include "libio.h" /* libio.h not pulled in by rtems */
+#include "libio_.h" /* libio_.h pulls in rtems */
/*
- * Semaphore to protect the io table
+ * Global variables used to manage the File Descriptor Table.
+ * IOP = IO Pointer.
*/
-Objects_Id rtems_libio_semaphore;
-
-#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
-#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
-
-extern unsigned32 rtems_libio_number_iops;
-rtems_libio_t *rtems_libio_iops;
-rtems_libio_t *rtems_libio_last_iop;
-
-#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
- &rtems_libio_iops[fd] : 0)
-
-#define rtems_libio_check_fd(fd) \
- do { \
- if ((unsigned32) (fd) >= rtems_libio_number_iops) \
- { \
- errno = EBADF; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_buffer(buffer) \
- do { \
- if ((buffer) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_count(count) \
- do { \
- if ((count) == 0) \
- { \
- return 0; \
- } \
- } while (0)
-
-#define rtems_libio_check_permissions(iop, flag) \
- do { \
- if (((iop)->flags & (flag)) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
+rtems_id rtems_libio_semaphore;
+rtems_libio_t *rtems_libio_iops;
+rtems_libio_t *rtems_libio_last_iop;
+rtems_libio_handler_t rtems_libio_handlers[15];
/*
- * External I/O handlers
- *
- * Space for all possible handlers is preallocated
- * to speed up dispatch to external handlers.
+ * rtems_register_libio_handler
+ *
+ * This function registers an external IO handler set. This lets
+ * other subsystems have their own versions of many of the system
+ * calls. For example, the networking code registers handlers which
+ * map the system calls for read() and write() to socket calls.
+ *
*/
-static rtems_libio_handler_t handlers[15];
-
-void
-rtems_register_libio_handler(
- int handler_flag,
- const rtems_libio_handler_t *handler
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
)
{
- int handler_index = rtems_file_descriptor_type_index(handler_flag);
+ int handler_index = rtems_file_descriptor_type_index( handler_flag );
+
if ((handler_index < 0) || (handler_index >= 15))
rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
- handlers[handler_index] = *handler;
-}
-
-/*
- * Called by bsp startup code to init the libio area.
- */
-void
-rtems_libio_init(void)
-{
- rtems_status_code rc;
-
- if (rtems_libio_number_iops > 0)
- {
- rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
- sizeof(rtems_libio_t));
- if (rtems_libio_iops == NULL)
- rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
-
- rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
- }
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_SEM,
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &rtems_libio_semaphore
- );
- if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_libio_handlers[handler_index] = *handler;
}
/*
- * Convert RTEMS status to a UNIX errno
+ * rtems_libio_init
+ *
+ * Called by BSP startup code to initialize the libio subsystem.
*/
-rtems_assoc_t errno_assoc[] = {
- { "OK", RTEMS_SUCCESSFUL, 0 },
- { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY },
- { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL },
- { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS },
- { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT },
- { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM },
- { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV },
- { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF},
- { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM},
- { "IO ERROR", RTEMS_IO_ERROR, EIO},
- { 0, 0, 0 },
-};
-
-static unsigned32
-rtems_libio_errno(rtems_status_code code)
+void rtems_libio_init( void )
{
- int rc;
-
- if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
- {
- errno = rc;
- return -1;
- }
- return -1;
+ rtems_status_code rc;
+
+ /*
+ * Allocate memory for the IOP Table
+ */
+
+ if ( rtems_libio_number_iops > 0 ) {
+ rtems_libio_iops =
+ (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t));
+
+ if (rtems_libio_iops == NULL)
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+
+ rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
+ }
+
+ /*
+ * Create the binary semaphore used to provide mutual exclusion
+ * on the IOP Table.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_SEM,
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_libio_semaphore
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ rtems_fatal_error_occurred( rc );
+
+ /*
+ * Initialize the base file system infrastructure.
+ */
+
+ rtems_filesystem_initialize();
}
/*
- * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
+ * rtems_libio_fcntl_flags
+ *
+ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
rtems_assoc_t access_modes_assoc[] = {
- { "READ", LIBIO_FLAGS_READ, O_RDONLY },
- { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
- { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
- { 0, 0, 0 },
+ { "READ", LIBIO_FLAGS_READ, O_RDONLY },
+ { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
+ { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
+ { 0, 0, 0 },
};
rtems_assoc_t status_flags_assoc[] = {
- { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
- { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
- { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
- { 0, 0, 0 },
+ { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
+ { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
+ { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
+ { 0, 0, 0 },
};
-static unsigned32
-rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+)
{
- unsigned32 flags = 0;
- unsigned32 access_modes;
+ unsigned32 flags = 0;
+ unsigned32 access_modes;
- /*
- * Access mode is a small integer
- */
-
- access_modes = fcntl_flags & O_ACCMODE;
- fcntl_flags &= ~O_ACCMODE;
- flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
+ /*
+ * Access mode is a small integer
+ */
+
+ access_modes = fcntl_flags & O_ACCMODE;
+ fcntl_flags &= ~O_ACCMODE;
+ flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
- /*
- * Everything else is single bits
- */
+ /*
+ * Everything else is single bits
+ */
- flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
- return flags;
+ flags |=
+ rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ return flags;
}
+/*
+ * rtems_libio_allocate
+ *
+ * This routine searches the IOP Table for an unused entry. If it
+ * finds one, it returns it. Otherwise, it returns NULL.
+ */
-static rtems_libio_t *
-rtems_libio_allocate(void)
+rtems_libio_t *rtems_libio_allocate( void )
{
- rtems_libio_t *iop;
- rtems_status_code rc;
-
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
- if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
- {
- /*
- * Got one; create a semaphore for it
- */
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &iop->sem
- );
- if (rc != RTEMS_SUCCESSFUL)
- goto failed;
-
- iop->flags = LIBIO_FLAGS_OPEN;
- goto done;
- }
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
+ if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
+ /*
+ * Got an IOP -- create a semaphore for it.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &iop->sem
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ goto failed;
+ iop->flags = LIBIO_FLAGS_OPEN;
+ goto done;
+ }
+
failed:
- iop = 0;
-
+ iop = 0;
+
done:
- rtems_semaphore_release(rtems_libio_semaphore);
- return iop;
+ rtems_semaphore_release( rtems_libio_semaphore );
+ return iop;
}
-static void
-rtems_libio_free(rtems_libio_t *iop)
-{
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- if (iop->sem)
- rtems_semaphore_delete(iop->sem);
- (void) memset(iop, 0, sizeof(*iop));
-
- rtems_semaphore_release(rtems_libio_semaphore);
-}
+/*
+ * rtems_libio_free
+ *
+ * This routine frees the resources associated with an IOP (file descriptor)
+ * and clears the slot in the IOP Table.
+ */
-int
-__rtems_open(
- const char *pathname,
- unsigned32 flag,
- unsigned32 mode)
+void rtems_libio_free(
+ rtems_libio_t *iop
+)
{
- rtems_status_code rc;
- rtems_libio_t *iop = 0;
- rtems_driver_name_t *np;
- rtems_libio_open_close_args_t args;
-
- /*
- * Additional external I/O handlers would be supported by
- * adding code to pick apart the pathname appropriately.
- * The networking code does not require changes here since
- * network file descriptors are obtained using socket(), not
- * open().
- */
-
- if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
- goto done;
-
- iop = rtems_libio_allocate();
- if (iop == 0)
- {
- rc = RTEMS_TOO_MANY;
- goto done;
- }
-
- iop->driver = np;
- iop->pathname = (char *) pathname;
- iop->flags |= rtems_libio_fcntl_flags(flag);
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.flags = iop->flags;
- args.mode = mode;
+ if (iop->sem)
+ rtems_semaphore_delete(iop->sem);
- rc = rtems_io_open(np->major, np->minor, (void *) &args);
-
-done:
-
- if (rc != RTEMS_SUCCESSFUL)
- {
- if (iop)
- rtems_libio_free(iop);
- return rtems_libio_errno(rc);
- }
-
- return iop - rtems_libio_iops;
-}
-
-int
-__rtems_close(
- int fd
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_open_close_args_t args;
- int status;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].close;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- status = (*fp)(fd);
- return status;
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+ (void) memset(iop, 0, sizeof(*iop));
- np = iop->driver;
-
- args.iop = iop;
- args.flags = 0;
- args.mode = 0;
-
- rc = rtems_io_close(np->major, np->minor, (void *) &args);
+ rtems_semaphore_release( rtems_libio_semaphore );
+}
- rtems_libio_free(iop);
+/*
+ * rtems_libio_is_open_files_in_fs
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * are any active file descriptors that refer to the atleast one node in the
+ * file system that we are trying to dismount.
+ *
+ * If there is at least one node in the file system referenced by the mount
+ * table entry a 1 is returned, otherwise a 0 is returned.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
- return 0;
-}
-
-int
-__rtems_read(
- int fd,
- void * buffer,
- unsigned32 count
- )
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t * fs_mt_entry
+)
{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].read;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+ rtems_libio_t *iop;
+ int result = 0;
- np = iop->driver;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
+ /*
+ * Look for any active file descriptor entry.
+ */
- rc = rtems_io_read(np->major, np->minor, (void *) &args);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- iop->offset += args.bytes_moved;
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
- return args.bytes_moved;
-}
-
-int
-__rtems_write(
- int fd,
- const void *buffer,
- unsigned32 count
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, const void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].write;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
+ if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
+ result = 1;
+ break;
+ }
}
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
-
- np = iop->driver;
-
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = (void *) buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
-
- rc = rtems_io_write(np->major, np->minor, (void *) &args);
+ }
- iop->offset += args.bytes_moved;
+ rtems_semaphore_release( rtems_libio_semaphore );
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
-
- return args.bytes_moved;
+ return result;
}
-int
-__rtems_ioctl(
- int fd,
- unsigned32 command,
- void * buffer)
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_ioctl_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, unsigned32 command, void *buffer);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, command, buffer);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+/*
+ * rtems_libio_is_file_open
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * given file refers to an active file descriptor.
+ *
+ * If the given file is open a 1 is returned, otherwise a 0 is returned.
+ */
- np = iop->driver;
+int rtems_libio_is_file_open(
+ void *node_access
+)
+{
+ rtems_libio_t *iop;
+ int result=0;
- args.iop = iop;
- args.command = command;
- args.buffer = buffer;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- rc = rtems_io_control(np->major, np->minor, (void *) &args);
+ /*
+ * Look for any active file descriptor entry.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- return args.ioctl_return;
-}
-
-/*
- * internal only??
- */
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
-int
-__rtems_lseek(
- int fd,
- rtems_libio_offset_t offset,
- int whence
- )
-{
- rtems_libio_t *iop;
+ if ( iop->pathinfo.node_access == node_access ) {
+ result = 1;
+ break;
+ }
+ }
+ }
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_semaphore_release( rtems_libio_semaphore );
- fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, offset, whence);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
-
- switch (whence)
- {
- case SEEK_SET:
- iop->offset = offset;
- break;
-
- case SEEK_CUR:
- iop->offset += offset;
- break;
-
- case SEEK_END:
- iop->offset = iop->size - offset;
- break;
-
- default:
- errno = EINVAL;
- return -1;
- }
- return 0;
+ return result;
}
diff --git a/c/src/exec/libcsupport/src/link.c b/c/src/exec/libcsupport/src/link.c
new file mode 100644
index 0000000000..1cee54d0bf
--- /dev/null
+++ b/c/src/exec/libcsupport/src/link.c
@@ -0,0 +1,60 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+ result = (*parent_loc.ops->evalformake)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 )
+ set_errno_and_return_minus_one( result );
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry )
+ set_errno_and_return_minus_one( EXDEV );
+
+ if ( !parent_loc.ops->link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start );
+}
diff --git a/c/src/exec/libcsupport/src/lseek.c b/c/src/exec/libcsupport/src/lseek.c
new file mode 100644
index 0000000000..514f8cd912
--- /dev/null
+++ b/c/src/exec/libcsupport/src/lseek.c
@@ -0,0 +1,93 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+
+#include "libio_.h"
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_lseek_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, offset, whence );
+ }
+
+ /*
+ * Now process the lseek().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ switch ( whence ) {
+ case SEEK_SET:
+ iop->offset = offset;
+ break;
+
+ case SEEK_CUR:
+ iop->offset += offset;
+ break;
+
+ case SEEK_END:
+ iop->offset = iop->size - offset;
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ( !iop->handlers->lseek )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->lseek)( iop, offset, whence );
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
+
diff --git a/c/src/exec/libcsupport/src/malloc.c b/c/src/exec/libcsupport/src/malloc.c
index fac38585a7..f164e45f6c 100644
--- a/c/src/exec/libcsupport/src/malloc.c
+++ b/c/src/exec/libcsupport/src/malloc.c
@@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize(
#ifdef MALLOC_STATS
/* zero all the stats */
- (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats));
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
#endif
MSBUMP(space_available, length);
@@ -220,9 +220,11 @@ void *malloc(
{
unsigned32 actual_size;
unsigned32 current_depth;
- status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size);
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
MSBUMP(lifetime_allocated, actual_size);
- current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
if (current_depth > rtems_malloc_stats.max_depth)
rtems_malloc_stats.max_depth = current_depth;
}
@@ -335,10 +337,12 @@ void free(
void malloc_dump(void)
{
- unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
printf("Malloc stats\n");
- printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
(unsigned int) rtems_malloc_stats.space_available / 1024,
(unsigned int) allocated / 1024,
/* avoid float! */
diff --git a/c/src/exec/libcsupport/src/mkdir.c b/c/src/exec/libcsupport/src/mkdir.c
new file mode 100644
index 0000000000..18fc7171c7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
+
diff --git a/c/src/exec/libcsupport/src/mkfifo.c b/c/src/exec/libcsupport/src/mkfifo.c
new file mode 100644
index 0000000000..6b3ece5650
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mkfifo.c
@@ -0,0 +1,25 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/c/src/exec/libcsupport/src/mknod.c b/c/src/exec/libcsupport/src/mknod.c
new file mode 100644
index 0000000000..4f83321ecd
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mknod.c
@@ -0,0 +1,60 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc );
+}
diff --git a/c/src/exec/libcsupport/src/mount.c b/c/src/exec/libcsupport/src/mount.c
new file mode 100644
index 0000000000..fa8cebc3f9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mount.c
@@ -0,0 +1,299 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+/*
+ * XXX
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+);
+
+int init_fs_mount_table( void );
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_options_t options;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Are the file system options valid?
+ */
+
+ options = get_file_system_options( fsoptions );
+ if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Is the file system type valid?
+ */
+
+ if ( fs_ops == NULL ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) );
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if( device )
+ sprintf( temp_mt_entry->dev, "%s", device );
+ else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+ if ( rtems_filesystem_evaluate_path(
+ mount_point,
+ RTEMS_LIBIO_PERMS_RWX,
+ &temp_loc ,
+ TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry
+ */
+
+ temp_mt_entry->mt_point_node.node_access = temp_loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = temp_loc.handlers;
+ temp_mt_entry->mt_point_node.ops = temp_loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !temp_loc.ops->mount ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( temp_loc.ops->mount( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ }
+ else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( !fs_ops->fsmount_me ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( fs_ops->fsmount_me( temp_mt_entry ) )
+ goto cleanup_and_bail;
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * get_file_system_options
+ *
+ * This routine will determine is the text string that represents the options
+ * that are to be used to mount the file system are actually valid. If the
+ * options are valid the appropriate file system options type will be returned
+ * to the calling routine.
+ */
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+)
+{
+ if ( strcmp( "RO", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_ONLY;
+ if ( strcmp( "RW", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_WRITE_ONLY;
+ else
+ return RTEMS_FILESYSTEM_BAD_OPTIONS;
+}
+
+
+
+/*
+ * search_mt_for_mount_point
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_point_node to the node describing the selected
+ * mount point.. If any of the mount table file system mount point nodes
+ * match the new file system selected mount point node, we are attempting
+ * to mount the new file system onto a node that already has a file system
+ * mounted to it. This is not a permitted operation.
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_point_node.node_access ==
+ location_of_mount_point->node_access )
+ return FOUND;
+ }
+ return NOT_FOUND;
+}
+
diff --git a/c/src/exec/libcsupport/src/newlibc.c b/c/src/exec/libcsupport/src/newlibc.c
index a6acc1c8d7..bea592a46e 100644
--- a/c/src/exec/libcsupport/src/newlibc.c
+++ b/c/src/exec/libcsupport/src/newlibc.c
@@ -1,21 +1,14 @@
-
/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
* COPYRIGHT (c) 1994 by Division Incorporated
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
- * Description:
- * Implementation of hooks for the CYGNUS newlib libc
- * These hooks set things up so that:
- * '_REENT' is switched at task switch time.
- *
- *
- * TODO:
- *
- * NOTE:
- *
* $Id$
*
*/
@@ -47,7 +40,21 @@
#include <stdio.h>
#endif
-#include "internal.h"
+/*
+ * Private routines
+ */
+
+void MY_task_set_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad,
+ rtems_unsigned32 note
+);
+
+rtems_unsigned32 MY_task_get_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad
+);
+
#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
@@ -304,7 +311,7 @@ libc_init(int reentrant)
rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
&libc_extension, &extension_id);
if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_fatal_error_occurred( rc );
libc_reentrant = reentrant;
}
@@ -353,11 +360,14 @@ int get_errno()
/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
#if !defined(RTEMS_UNIX) && !defined(_AM29K)
+#if !defined(pc386)
void _exit(int status)
{
libc_wrapup(); /* Why? XXX */
rtems_shutdown_executive(status);
}
+#endif
+
#else
void exit(int status)
@@ -426,4 +436,46 @@ unsigned int sleep(
#endif
+/*
+ * Newlib Interface Support
+ *
+ * Routines to Access Internal RTEMS Resources without violating
+ * kernel visibility.
+ *
+ */
+
+void MY_task_set_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad,
+ unsigned32 note
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( api )
+ api->Notepads[ notepad ] = note;
+}
+
+
+unsigned32 MY_task_get_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ return api->Notepads[ notepad ];
+}
+
+void *MY_CPU_Context_FP_start(
+ void *base,
+ unsigned32 offset
+)
+{
+ return _CPU_Context_Fp_start( base, offset );
+}
#endif
diff --git a/c/src/exec/libcsupport/src/no_libc.c b/c/src/exec/libcsupport/src/no_libc.c
index 5a58ba761c..4bd02c4b27 100644
--- a/c/src/exec/libcsupport/src/no_libc.c
+++ b/c/src/exec/libcsupport/src/no_libc.c
@@ -1,6 +1,4 @@
-
-/* no_libc.h
- *
+/*
* This file contains stubs for the reentrancy hooks when
* an unknown C library is used.
*
@@ -17,15 +15,15 @@
#include <rtems.h>
-#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
#include "libcsupport.h"
-#include "internal.h"
#include <stdlib.h> /* for free() */
-void
-libc_init(int reentrant)
+void libc_init(
+ int reentrant
+)
{
}
@@ -34,11 +32,15 @@ void libc_suspend_main(void)
}
-void libc_global_exit(rtems_unsigned32 code)
+void libc_global_exit(
+ rtems_unsigned32 code
+)
{
}
-void _exit(int status)
+void _exit(
+ int status
+)
{
}
diff --git a/c/src/exec/libcsupport/src/open.c b/c/src/exec/libcsupport/src/open.c
new file mode 100644
index 0000000000..4cdf5acf35
--- /dev/null
+++ b/c/src/exec/libcsupport/src/open.c
@@ -0,0 +1,202 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and eitehr the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * Additional external I/O handlers would be supported by adding
+ * code to pick apart the pathname appropriately. The networking
+ * code does not require changes here since network file
+ * descriptors are obtained using socket(), not open().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+
+ status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ goto done;
+ }
+
+ /*
+ * Fill in the file control block based on the temp_loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = temp_loc.handlers;
+ iop->file_info = temp_loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = temp_loc;
+
+ if ( !iop->handlers->open ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ set_errno_and_return_minus_one( rc );
+ }
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/opendir.c b/c/src/exec/libcsupport/src/opendir.c
index e303eb28e5..f0e9488684 100644
--- a/c/src/exec/libcsupport/src/opendir.c
+++ b/c/src/exec/libcsupport/src/opendir.c
@@ -1,17 +1,85 @@
/*
* opendir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
-DIR *opendir(
- const char *name
-)
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
{
- return NULL;
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
}
diff --git a/c/src/exec/libcsupport/src/pathconf.c b/c/src/exec/libcsupport/src/pathconf.c
new file mode 100644
index 0000000000..e19d1329f4
--- /dev/null
+++ b/c/src/exec/libcsupport/src/pathconf.c
@@ -0,0 +1,38 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/c/src/lib/libc/_execve.c b/c/src/exec/libcsupport/src/pipe.c
index d1ad365b57..35dcf627bb 100644
--- a/c/src/lib/libc/_execve.c
+++ b/c/src/exec/libcsupport/src/pipe.c
@@ -1,9 +1,5 @@
-#include <rtems.h>
-
-#if defined(RTEMS_NEWLIB)
/*
- * RTEMS Dummy _execveImplementation
- *
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -16,16 +12,12 @@
* $Id$
*/
-#include <unistd.h>
#include <errno.h>
-int _execve(
- const char *path,
- char *const argv[],
- char *const environ[]
+int pipe(
+ int filsdes[2]
)
{
errno = ENOSYS;
return -1;
}
-#endif
diff --git a/c/src/exec/libcsupport/src/read.c b/c/src/exec/libcsupport/src/read.c
new file mode 100644
index 0000000000..150fe675ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/read.c
@@ -0,0 +1,84 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int read(
+ int fd,
+ void *buffer,
+ unsigned32 count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_read_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the read().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/readdir.c b/c/src/exec/libcsupport/src/readdir.c
index d592a62b99..f950d56171 100644
--- a/c/src/exec/libcsupport/src/readdir.c
+++ b/c/src/exec/libcsupport/src/readdir.c
@@ -1,14 +1,77 @@
/*
* readdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
-struct dirent *readdir(
- register DIR *dirp
-)
-{
- return NULL;
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
}
diff --git a/c/src/exec/libcsupport/src/readlink.c b/c/src/exec/libcsupport/src/readlink.c
new file mode 100644
index 0000000000..22de51e88f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/readlink.c
@@ -0,0 +1,43 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if (!buf)
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( !loc.ops->readlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->readlink)( &loc, buf, bufsize );
+}
diff --git a/c/src/exec/libcsupport/src/rewinddir.c b/c/src/exec/libcsupport/src/rewinddir.c
index c85e6fd4d0..04313a6042 100644
--- a/c/src/exec/libcsupport/src/rewinddir.c
+++ b/c/src/exec/libcsupport/src/rewinddir.c
@@ -1,7 +1,14 @@
/*
* rewinddir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/types.h>
@@ -15,6 +22,14 @@ void rewinddir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
+
}
diff --git a/c/src/exec/libcsupport/src/rmdir.c b/c/src/exec/libcsupport/src/rmdir.c
new file mode 100644
index 0000000000..6c0331087f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/rmdir.c
@@ -0,0 +1,56 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libio_.h"
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.ops->rmnod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->rmnod)( &loc );
+}
diff --git a/c/src/exec/libcsupport/src/scandir.c b/c/src/exec/libcsupport/src/scandir.c
index 380415dd97..9ba1cb7bec 100644
--- a/c/src/exec/libcsupport/src/scandir.c
+++ b/c/src/exec/libcsupport/src/scandir.c
@@ -1,7 +1,50 @@
/*
* scandir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
@@ -9,15 +52,98 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-int scandir(
- const char *dirname,
- struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*dcomp)(const void *, const void *)
-)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d, *p, **names;
+ register size_t nitems;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1);
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1); /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
{
- errno = ENOSYS;
- return -1;
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
}
diff --git a/c/src/exec/libcsupport/src/seekdir.c b/c/src/exec/libcsupport/src/seekdir.c
index e591adbb9f..80802b56c6 100644
--- a/c/src/exec/libcsupport/src/seekdir.c
+++ b/c/src/exec/libcsupport/src/seekdir.c
@@ -1,7 +1,14 @@
/*
* seekdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -12,10 +19,20 @@
#include <errno.h>
void seekdir(
- DIR *dirp,
- long loc
+ DIR *dirp,
+ long loc
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
}
diff --git a/c/src/exec/libcsupport/src/stat.c b/c/src/exec/libcsupport/src/stat.c
new file mode 100644
index 0000000000..8ad7e61511
--- /dev/null
+++ b/c/src/exec/libcsupport/src/stat.c
@@ -0,0 +1,79 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int stat(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ return (*loc.handlers->fstat)( &loc, buf );
+}
+#endif
+
+/*
+ * _stat_r
+ *
+ * This is the Newlib dependent reentrant version of stat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _stat_r(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return stat( path, buf );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/symlink.c b/c/src/exec/libcsupport/src/symlink.c
new file mode 100644
index 0000000000..ca9673f51b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/symlink.c
@@ -0,0 +1,34 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ return (*loc.ops->symlink)( &loc, actualpath, name_start);
+}
+
diff --git a/c/src/exec/libcsupport/src/tcdrain.c b/c/src/exec/libcsupport/src/tcdrain.c
index 585871cc90..c2749a90e1 100644
--- a/c/src/exec/libcsupport/src/tcdrain.c
+++ b/c/src/exec/libcsupport/src/tcdrain.c
@@ -1,9 +1,15 @@
/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcdrain.
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
+ * $Id$
*/
#include <rtems.h>
@@ -13,14 +19,15 @@
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>
+#include <sys/ioctl.h>
-#include "internal.h"
#include "libio.h"
-int
-tcdrain(int fd)
+int tcdrain(
+ int fd
+)
{
- return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0);
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
}
#endif
diff --git a/c/src/exec/libcsupport/src/tcgetattr.c b/c/src/exec/libcsupport/src/tcgetattr.c
new file mode 100644
index 0000000000..2d3e4d7e3c
--- /dev/null
+++ b/c/src/exec/libcsupport/src/tcgetattr.c
@@ -0,0 +1,33 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/tcsetattr.c b/c/src/exec/libcsupport/src/tcsetattr.c
new file mode 100644
index 0000000000..c0ed509a0f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/tcsetattr.c
@@ -0,0 +1,38 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+#include "libio_.h"
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ if ( opt != TCSANOW )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/telldir.c b/c/src/exec/libcsupport/src/telldir.c
index eee8d925ec..cea6cc08cb 100644
--- a/c/src/exec/libcsupport/src/telldir.c
+++ b/c/src/exec/libcsupport/src/telldir.c
@@ -1,7 +1,14 @@
/*
* telldir() - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -9,15 +16,24 @@
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
-#include <rtems.h>
-#include "libio.h"
+#include "libio_.h"
+
long telldir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ rtems_libio_t *iop;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
}
diff --git a/c/src/exec/libcsupport/src/truncate.c b/c/src/exec/libcsupport/src/truncate.c
new file mode 100644
index 0000000000..145e596654
--- /dev/null
+++ b/c/src/exec/libcsupport/src/truncate.c
@@ -0,0 +1,41 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
+
diff --git a/c/src/exec/libcsupport/src/umask.c b/c/src/exec/libcsupport/src/umask.c
new file mode 100644
index 0000000000..35229a30a1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/umask.c
@@ -0,0 +1,30 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libio_.h"
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/c/src/exec/libcsupport/src/unixlibc.c b/c/src/exec/libcsupport/src/unixlibc.c
index 3e757e313d..a581d95534 100644
--- a/c/src/exec/libcsupport/src/unixlibc.c
+++ b/c/src/exec/libcsupport/src/unixlibc.c
@@ -1,5 +1,15 @@
/*
* $Id$
+ * UNIX Port C Library Support
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <rtems.h>
diff --git a/c/src/exec/libcsupport/src/unlink.c b/c/src/exec/libcsupport/src/unlink.c
new file mode 100644
index 0000000000..d4a5520bcb
--- /dev/null
+++ b/c/src/exec/libcsupport/src/unlink.c
@@ -0,0 +1,44 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ if ( !loc.ops->unlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->unlink)( &loc );
+}
diff --git a/c/src/exec/libcsupport/src/unmount.c b/c/src/exec/libcsupport/src/unmount.c
new file mode 100644
index 0000000000..f50e63ff42
--- /dev/null
+++ b/c/src/exec/libcsupport/src/unmount.c
@@ -0,0 +1,214 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+);
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a mount_path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *mount_path
+)
+{
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_mount_table_entry_t temp_mt_entry;
+ int result;
+
+ /*
+ * Are there any file systems below the mount_path specified
+ */
+
+ status = file_systems_below_this_mountpoint(
+ mount_path,
+ &temp_loc,
+ &temp_mt_entry
+ );
+
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Is the current node reference pointing to a node in the file system
+ * we are attempting to unmount ?
+ */
+
+ if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being mounted on to do its cleanup.
+ * XXX - Did I change these correctly ??? It looks like either I did
+ * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped.
+ * XXX Add to the mt_point_node unmount to set the mt_entry back to null
+ * XXX I will step off in space when evaluating past the end of the node.
+ */
+
+ if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Run the unmount function for the subordinate file system.
+ */
+
+ if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the file system to clean up.
+ */
+
+ result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry );
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry );
+
+ /*
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ free( temp_loc.mt_entry );
+
+ return result;
+
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+ rtems_filesystem_mount_table_entry_t *current_fs_mt_entry;
+
+ /*
+ * Is the mount_path even a valid node name in the existing tree?
+ */
+
+ if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) )
+ return -1;
+
+ /*
+ * Look for the node defined in temp_loc as a mount point in the
+ * mount table chain.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.node_access ==
+ temp_loc->node_access ) {
+ current_fs_mt_entry = the_mount_entry;
+ *temp_loc = current_fs_mt_entry->mt_fs_root;
+ goto after_real_mount_point_found;
+ }
+ }
+ set_errno_and_return_minus_one( EACCES );
+
+
+after_real_mount_point_found:
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+
+ /*
+ * Exclude the current file systems mount table entry from the test
+ */
+
+ if ( current_fs_mt_entry != the_mount_entry ) {
+ if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) {
+
+ /*
+ * There is at least one fs below the fs on the mount_path.
+ */
+ set_errno_and_return_minus_one( EBUSY );
+ }
+ }
+ }
+
+ *temp_mt_entry = *current_fs_mt_entry;
+
+ return 0;
+}
diff --git a/c/src/exec/libcsupport/src/utime.c b/c/src/exec/libcsupport/src/utime.c
new file mode 100644
index 0000000000..f1a12ee1b2
--- /dev/null
+++ b/c/src/exec/libcsupport/src/utime.c
@@ -0,0 +1,35 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime );
+}
diff --git a/c/src/exec/libcsupport/src/write.c b/c/src/exec/libcsupport/src/write.c
new file mode 100644
index 0000000000..7e0953bb90
--- /dev/null
+++ b/c/src/exec/libcsupport/src/write.c
@@ -0,0 +1,92 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int write( /* XXX this should return a ssize_t */
+ int fd,
+ const void *buffer,
+ unsigned32 count /* XXX this should be a size_t */
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_write_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the write() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->write )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+long _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/exec/libfs/src/imfs/deviceio.c b/c/src/exec/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/exec/libfs/src/imfs/imfs.h b/c/src/exec/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/exec/libfs/src/imfs/imfs_chown.c b/c/src/exec/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_creat.c b/c/src/exec/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_debug.c b/c/src/exec/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_directory.c b/c/src/exec/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_eval.c b/c/src/exec/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_fchmod.c b/c/src/exec/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_free.c b/c/src/exec/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_getchild.c b/c/src/exec/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_gtkn.c b/c/src/exec/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_init.c b/c/src/exec/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_initsupp.c b/c/src/exec/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_link.c b/c/src/exec/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_mknod.c b/c/src/exec/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_mount.c b/c/src/exec/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_ntype.c b/c/src/exec/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_readlink.c b/c/src/exec/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_rmnod.c b/c/src/exec/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_stat.c b/c/src/exec/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_symlink.c b/c/src/exec/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_unlink.c b/c/src/exec/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_unmount.c b/c/src/exec/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_utime.c b/c/src/exec/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/ioman.c b/c/src/exec/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/c/src/exec/libfs/src/imfs/memfile.c b/c/src/exec/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/exec/posix/include/sys/Makefile.in b/c/src/exec/posix/include/sys/Makefile.in
index d7d9281094..e787a7a977 100644
--- a/c/src/exec/posix/include/sys/Makefile.in
+++ b/c/src/exec/posix/include/sys/Makefile.in
@@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
#H_PIECES=utsname
-H_PIECES=
+H_PIECES=utime ioctl
H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
SRCS=$(H_FILES)
diff --git a/c/src/exec/posix/src/getpid.c b/c/src/exec/posix/src/getpid.c
index b42981398a..8e912adf39 100644
--- a/c/src/exec/posix/src/getpid.c
+++ b/c/src/exec/posix/src/getpid.c
@@ -20,3 +20,22 @@ pid_t getpid( void )
{
return _Objects_Local_node;
}
+
+/*
+ * _getpid_r
+ *
+ * This is the Newlib dependent reentrant version of getpid().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+pid_t _getpid_r(
+ struct _reent *ptr
+)
+{
+ return getpid();
+}
+#endif
+
diff --git a/c/src/exec/posix/src/psignal.c b/c/src/exec/posix/src/psignal.c
index 5db634a924..1450164021 100644
--- a/c/src/exec/posix/src/psignal.c
+++ b/c/src/exec/posix/src/psignal.c
@@ -1222,6 +1222,26 @@ int kill(
}
/*
+ * _kill_r
+ *
+ * This is the Newlib dependent reentrant version of kill().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _kill_r(
+ struct _reent *ptr,
+ pid_t pid,
+ int sig
+)
+{
+ return kill( pid, sig );
+}
+#endif
+
+/*
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
*/
diff --git a/c/src/exec/posix/sys/Makefile.in b/c/src/exec/posix/sys/Makefile.in
index d7d9281094..e787a7a977 100644
--- a/c/src/exec/posix/sys/Makefile.in
+++ b/c/src/exec/posix/sys/Makefile.in
@@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
#H_PIECES=utsname
-H_PIECES=
+H_PIECES=utime ioctl
H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
SRCS=$(H_FILES)
diff --git a/c/src/exec/sapi/src/io.c b/c/src/exec/sapi/src/io.c
index 92de490885..d6e669c4fc 100644
--- a/c/src/exec/sapi/src/io.c
+++ b/c/src/exec/sapi/src/io.c
@@ -92,6 +92,7 @@ void _IO_Initialize_all_drivers( void )
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_register_name(
char *device_name,
rtems_device_major_number major,
@@ -124,6 +125,7 @@ rtems_status_code rtems_io_register_name(
return RTEMS_TOO_MANY;
}
+#endif
/*PAGE
*
@@ -140,6 +142,7 @@ rtems_status_code rtems_io_register_name(
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_lookup_name(
const char *name,
rtems_driver_name_t **device_info
@@ -161,6 +164,7 @@ rtems_status_code rtems_io_lookup_name(
*device_info = 0;
return RTEMS_UNSATISFIED;
}
+#endif
/*PAGE
diff --git a/c/src/lib/include/rtems/libio.h b/c/src/lib/include/rtems/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/lib/include/rtems/libio.h
+++ b/c/src/lib/include/rtems/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/lib/include/rtems/libio_.h b/c/src/lib/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/lib/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/lib/libbsp/shared/bsplibc.c b/c/src/lib/libbsp/shared/bsplibc.c
index 164e33a016..faa5e436c7 100644
--- a/c/src/lib/libbsp/shared/bsplibc.c
+++ b/c/src/lib/libbsp/shared/bsplibc.c
@@ -22,7 +22,7 @@ void bsp_libc_init(
/*
* Init the RTEMS libio facility to provide UNIX-like system
- * calls for use by newlib (ie: provide __rtems_open, __rtems_close, etc)
+ * calls for use by newlib (ie: provide open, close, etc)
* Uses malloc() to get area for the iops, so must be after malloc init
*/
diff --git a/c/src/lib/libbsp/shared/bsppost.c b/c/src/lib/libbsp/shared/bsppost.c
index d3d14786ce..28a41bf4ea 100644
--- a/c/src/lib/libbsp/shared/bsppost.c
+++ b/c/src/lib/libbsp/shared/bsppost.c
@@ -22,13 +22,13 @@ bsp_postdriver_hook(void)
error_code = 'S' << 24 | 'T' << 16;
- if ((stdin_fd = __rtems_open("/dev/console", O_RDONLY, 0)) == -1)
+ if ((stdin_fd = open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
- if ((stdout_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1)
+ if ((stdout_fd = open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
- if ((stderr_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1)
+ if ((stderr_fd = open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
diff --git a/c/src/lib/libc/CASES b/c/src/lib/libc/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/c/src/lib/libc/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/c/src/lib/libc/Makefile.in b/c/src/lib/libc/Makefile.in
index c9fbf72795..d3bc2afbc1 100644
--- a/c/src/lib/libc/Makefile.in
+++ b/c/src/lib/libc/Makefile.in
@@ -11,34 +11,59 @@ PROJECT_ROOT = @PROJECT_ROOT@
LIBNAME=libcsupport.a
LIB=${ARCH}/${LIBNAME}
-# define TARGET_PIECES later based on RTEMS_CPU definition
+BASE_FS_PIECES=base_fs mount unmount ioman \
+ libio eval
+
+IMFS_PIECES= imfs_chown imfs_creat imfs_directory imfs_eval imfs_free \
+ imfs_gtkn imfs_init imfs_link imfs_mknod imfs_mount imfs_fchmod \
+ imfs_rmnod imfs_unlink imfs_unmount imfs_utime imfs_ntype imfs_stat \
+ imfs_getchild memfile deviceio imfs_handlers imfs_debug imfs_symlink \
+ imfs_readlink
+
+TERMIOS_PIECES= cfgetispeed cfgetospeed cfsetispeed cfsetospeed \
+ tcgetattr tcsetattr tcdrain termios
+
+SYSTEM_CALL_PIECES=\
+ open close read write lseek ioctl \
+ mkdir mknod mkfifo rmdir chdir \
+ chmod fchmod chown \
+ link unlink umask ftruncate utime \
+ fstat fcntl fpathconf getdents \
+ fsync fdatasync pipe dup dup2 \
+ symlink readlink
+
+DIRECTORY_SCAN_PIECES=\
+ opendir closedir readdir rewinddir scandir seekdir telldir
+
+LIBC_GLUE_PIECES=\
+ malloc __brk __sbrk \
+ __gettod __times \
+ truncate access stat pathconf \
+ newlibc no_libc unixlibc hosterr
# C and C++ source names, if any, go here -- minus the .c or .cc
-C_PIECES=__times _execve malloc syscalls \
- no_libc support libio hosterr tcattr tcdrain \
- cfiospeed termios $(TARGET_PIECES)
+C_PIECES=\
+ $(LIBC_GLUE_PIECES) \
+ $(TERMIOS_PIECES) \
+ $(SYSTEM_CALL_PIECES) \
+ $(DIRECTORY_SCAN_PIECES) \
+ $(BASE_FS_PIECES) \
+ $(IMFS_PIECES)
+
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=$(srcdir)/libcsupport.h
SYS_H_FILES=
RTEMS_H_FILES=$(srcdir)/libio.h
-PRIVATE_H_FILES=$(srcdir)/internal.h
INSTALLED_H_FILES=$(srcdir)/libio.h $(srcdir)/libcsupport.h
-SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES) $(PRIVATE_H_FILES)
+SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/lib.cfg
-ifeq ($(RTEMS_CPU),unix)
-TARGET_PIECES=unixlibc
-else
-TARGET_PIECES=__brk __gettod newlibc newlibif newlibifr \
- getdents readdir opendir closedir rewinddir scandir seekdir telldir
-endif
-
#
# Add local stuff here using +=
#
diff --git a/c/src/lib/libc/TODO b/c/src/lib/libc/TODO
new file mode 100644
index 0000000000..9d894688d9
--- /dev/null
+++ b/c/src/lib/libc/TODO
@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
diff --git a/c/src/lib/libc/__brk.c b/c/src/lib/libc/__brk.c
index 4dab22c729..24efa93adb 100644
--- a/c/src/lib/libc/__brk.c
+++ b/c/src/lib/libc/__brk.c
@@ -1,10 +1,7 @@
-#if !defined(RTEMS_UNIX)
-
/*
- * RTEMS "Broken" __brk/__sbrk Implementation
- *
- * NOTE: sbrk is BSP provided.
+ * RTEMS "Broken" __brk Implementation
*
+ * NOTE: sbrk() is provided by each BSP.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,27 +15,15 @@
*/
#include <rtems.h>
+#if !defined(RTEMS_UNIX)
-#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#ifdef RTEMS_NEWLIB
-#include <reent.h>
-#endif
-#include <unistd.h>
-
-/* we use RTEMS for memory management. We don't need sbrk */
-void * __sbrk(int incr)
-{
- errno = EINVAL;
- return (void *)0;
-}
-
-int __brk( const void *endds )
+int __brk(
+ const void *endds
+)
{
errno = EINVAL;
return -1;
}
-
#endif
diff --git a/c/src/lib/libc/__gettod.c b/c/src/lib/libc/__gettod.c
index dc83c47ce4..16857da870 100644
--- a/c/src/lib/libc/__gettod.c
+++ b/c/src/lib/libc/__gettod.c
@@ -1,11 +1,5 @@
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-
-#include <rtems.h>
-
-#if !defined(RTEMS_UNIX)
/*
- * RTEMS gettimeofday Implementation
- *
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,6 +12,11 @@
* $Id$
*/
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
#ifdef RTEMS_NEWLIB
#include <sys/reent.h>
#endif
@@ -61,7 +60,7 @@ int gettimeofday(
*
* NOTE: XXX this routine should really be in the executive proper.
*/
-
+
rtems_interrupt_disable(level);
seconds = _TOD_Seconds_since_epoch;
microseconds = _TOD_Current.ticks;
@@ -86,7 +85,7 @@ int gettimeofday(
return 0;
}
-#if defined(RTEMS_NEWLIB)
+#if defined(RTEMS_NEWLIB)
/*
* "Reentrant" version
@@ -102,7 +101,7 @@ int _gettimeofday_r(
}
/*
- * "System call" version
+ * "System call" version
*/
int _gettimeofday(
diff --git a/c/src/lib/libc/__sbrk.c b/c/src/lib/libc/__sbrk.c
new file mode 100644
index 0000000000..b1d31467fd
--- /dev/null
+++ b/c/src/lib/libc/__sbrk.c
@@ -0,0 +1,29 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/c/src/lib/libc/__times.c b/c/src/lib/libc/__times.c
index 635bf8e062..5f7525ec5f 100644
--- a/c/src/lib/libc/__times.c
+++ b/c/src/lib/libc/__times.c
@@ -1,6 +1,5 @@
/*
- * RTEMS _times Implementation
- *
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -25,8 +24,8 @@ clock_t _times(
struct tms *ptms
)
{
- rtems_status_code status;
- rtems_interval ticks_since_boot;
+ rtems_status_code status;
+ rtems_interval ticks;
if ( !ptms ) {
errno = EFAULT;
@@ -34,21 +33,19 @@ clock_t _times(
}
/* "POSIX" does not seem to allow for not having a TOD */
- status = rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &ticks_since_boot
- );
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
if ( status != RTEMS_SUCCESSFUL ) {
assert( 0 );
return -1;
}
/*
- * RTEMS has no notion of system versus user time and does
- * not (as of 3.2.0) keep track of CPU usage on a per task basis.
+ * RTEMS has no notion of system versus user time and although
+ * a way to keep track of per task CPU usage was added since
+ * 3.6.0, this routine does not utilize it yet.
*/
- ptms->tms_utime = ticks_since_boot;
+ ptms->tms_utime = ticks;
ptms->tms_stime = 0;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
@@ -56,6 +53,12 @@ clock_t _times(
return 0;
}
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
clock_t times(
struct tms *ptms
)
@@ -63,12 +66,21 @@ clock_t times(
return _times( ptms );
}
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
clock_t _times_r(
struct _reent *ptr,
struct tms *ptms
)
{
- return _times(ptms);
+ return _times( ptms );
}
#endif
diff --git a/c/src/lib/libc/access.c b/c/src/lib/libc/access.c
new file mode 100644
index 0000000000..a8be44a9a3
--- /dev/null
+++ b/c/src/lib/libc/access.c
@@ -0,0 +1,46 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/base_fs.c b/c/src/lib/libc/base_fs.c
new file mode 100644
index 0000000000..c8c23e5b43
--- /dev/null
+++ b/c/src/lib/libc/base_fs.c
@@ -0,0 +1,81 @@
+/*
+ * Base file system initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_filesystem_location_info_t rtems_filesystem_current;
+rtems_filesystem_location_info_t rtems_filesystem_root;
+nlink_t rtems_filesystem_link_counts;
+
+/*
+ * Default mode for created files.
+ */
+
+mode_t rtems_filesystem_umask;
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system with one instantiation
+ * of the IMFS with a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *first_entry;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = S_IWOTH | S_IROTH;
+
+ init_fs_mount_table();
+
+ status = mount(
+ &first_entry,
+ &IMFS_ops,
+ "RW",
+ NULL,
+ NULL );
+ if( status == -1 ){
+ rtems_fatal_error_occurred( 0xABCD0002 );
+ }
+
+ rtems_filesystem_link_counts = 0;
+
+ rtems_filesystem_root = first_entry->mt_fs_root;
+
+ rtems_filesystem_current = rtems_filesystem_root;
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+}
diff --git a/c/src/lib/libc/cfgetispeed.c b/c/src/lib/libc/cfgetispeed.c
new file mode 100644
index 0000000000..61d97cb2f1
--- /dev/null
+++ b/c/src/lib/libc/cfgetispeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/c/src/lib/libc/cfgetospeed.c b/c/src/lib/libc/cfgetospeed.c
new file mode 100644
index 0000000000..8815d436e9
--- /dev/null
+++ b/c/src/lib/libc/cfgetospeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/c/src/lib/libc/cfiospeed.c b/c/src/lib/libc/cfiospeed.c
deleted file mode 100644
index c2f40d3892..0000000000
--- a/c/src/lib/libc/cfiospeed.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines cfgetispeed, cfgetospeed, cfsetispeed and cfsetospeed.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-speed_t
-cfgetospeed(const struct termios *tp)
-{
- return tp->c_cflag & CBAUD;
-}
-
-int
-cfsetospeed(struct termios *tp, speed_t speed)
-{
- if (speed & ~CBAUD) {
- errno = EINVAL;
- return -1;
- }
- tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
- return 0;
-}
-
-speed_t
-cfgetispeed(const struct termios *tp)
-{
- return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
-}
-
-int
-cfsetispeed(struct termios *tp, speed_t speed)
-{
- if (speed & ~CBAUD) {
- errno = EINVAL;
- return -1;
- }
- tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
- return 0;
-}
-
-#endif
diff --git a/c/src/lib/libc/cfsetispeed.c b/c/src/lib/libc/cfsetispeed.c
new file mode 100644
index 0000000000..37d3cd0584
--- /dev/null
+++ b/c/src/lib/libc/cfsetispeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/c/src/lib/libc/cfsetospeed.c b/c/src/lib/libc/cfsetospeed.c
new file mode 100644
index 0000000000..f01237103b
--- /dev/null
+++ b/c/src/lib/libc/cfsetospeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/c/src/lib/libc/chdir.c b/c/src/lib/libc/chdir.c
new file mode 100644
index 0000000000..4acbc8cfe0
--- /dev/null
+++ b/c/src/lib/libc/chdir.c
@@ -0,0 +1,50 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/chmod.c b/c/src/lib/libc/chmod.c
new file mode 100644
index 0000000000..fa57d50691
--- /dev/null
+++ b/c/src/lib/libc/chmod.c
@@ -0,0 +1,40 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "libio_.h"
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.handlers->fchmod)( &loc, mode );
+}
diff --git a/c/src/lib/libc/chown.c b/c/src/lib/libc/chown.c
new file mode 100644
index 0000000000..189096dcd1
--- /dev/null
+++ b/c/src/lib/libc/chown.c
@@ -0,0 +1,38 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "libio_.h"
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->chown )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->chown)( &temp_loc, owner, group );
+}
diff --git a/c/src/lib/libc/close.c b/c/src/lib/libc/close.c
new file mode 100644
index 0000000000..94ddb45c90
--- /dev/null
+++ b/c/src/lib/libc/close.c
@@ -0,0 +1,70 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+ int status;
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ int (*fp)(int fd);
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+ status = (*fp)( fd );
+ return status;
+ }
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+
+ if ( !iop->handlers )
+ set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->close )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->close)( iop );
+
+ rtems_libio_free( iop );
+
+ if (rc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( rc );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/c/src/lib/libc/closedir.c b/c/src/lib/libc/closedir.c
index 5edb3499e6..4d948ec95b 100644
--- a/c/src/lib/libc/closedir.c
+++ b/c/src/lib/libc/closedir.c
@@ -1,9 +1,44 @@
/*
* closedir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <dirent.h>
@@ -11,10 +46,25 @@
#include <unistd.h>
#include <errno.h>
-int closedir(
- register DIR *dirp
-)
+
+#include "libio_.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
{
- errno = ENOSYS;
- return -1;
+ int fd;
+
+ if ( !dirp )
+ set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
}
diff --git a/c/src/lib/libc/deviceio.c b/c/src/lib/libc/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/lib/libc/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/lib/libc/dup.c b/c/src/lib/libc/dup.c
new file mode 100644
index 0000000000..c17db588a7
--- /dev/null
+++ b/c/src/lib/libc/dup.c
@@ -0,0 +1,23 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/c/src/lib/libc/dup2.c b/c/src/lib/libc/dup2.c
new file mode 100644
index 0000000000..5653425708
--- /dev/null
+++ b/c/src/lib/libc/dup2.c
@@ -0,0 +1,49 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "libio_.h"
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/c/src/lib/libc/eval.c b/c/src/lib/libc/eval.c
new file mode 100644
index 0000000000..bf7dd1c126
--- /dev/null
+++ b/c/src/lib/libc/eval.c
@@ -0,0 +1,74 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include "libio_.h"
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( follow_link ) {
+
+ if ( !pathloc->ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ type = (*pathloc->ops->node_type)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->eval_link)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
diff --git a/c/src/lib/libc/fchmod.c b/c/src/lib/libc/fchmod.c
new file mode 100644
index 0000000000..a3ca4507ab
--- /dev/null
+++ b/c/src/lib/libc/fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "libio_.h"
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fchmod().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode );
+}
+
diff --git a/c/src/lib/libc/fcntl.c b/c/src/lib/libc/fcntl.c
new file mode 100644
index 0000000000..f6f33534ab
--- /dev/null
+++ b/c/src/lib/libc/fcntl.c
@@ -0,0 +1,111 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include "libio_.h"
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ va_list ap;
+ rtems_libio_t *iop;
+
+ va_start( ap, cmd );
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fcntl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ /*
+ * This is how it appears that this case should work:
+ *
+ * filedes2 = va_arg( ap, int )
+ * if filedes2 is 0
+ * duplicate fd into a new descriptor
+ * else
+ * duplicate fd into specified descriptor after error checking it
+ *
+ * See dup2() in case we can eliminate stuff in there.
+ */
+ return -1;
+
+ case F_GETFD: /* get f_flags */
+ if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
+ return 1;
+ return 0;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ return 0;
+
+ case F_GETFL: /* more flags (cloexec) */
+ return -1;
+
+ case F_SETFL:
+ return -1;
+
+ case F_GETLK:
+ return -1;
+
+ case F_SETLK:
+ return -1;
+
+ case F_SETLKW:
+ return -1;
+
+ case F_SETOWN: /* for sockets. */
+ return -1;
+
+ case F_GETOWN: /* for sockets. */
+ return -1;
+
+ default:
+ break;
+ }
+ return -1;
+}
diff --git a/c/src/lib/libc/fdatasync.c b/c/src/lib/libc/fdatasync.c
new file mode 100644
index 0000000000..58a4c4e118
--- /dev/null
+++ b/c/src/lib/libc/fdatasync.c
@@ -0,0 +1,45 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fdatasync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync)( iop );
+}
diff --git a/c/src/lib/libc/fpathconf.c b/c/src/lib/libc/fpathconf.c
new file mode 100644
index 0000000000..ea2377e15b
--- /dev/null
+++ b/c/src/lib/libc/fpathconf.c
@@ -0,0 +1,91 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then it is an error since fpathconf() is not included in the
+ * set.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the information request.
+ */
+
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/c/src/lib/libc/fstat.c b/c/src/lib/libc/fstat.c
new file mode 100644
index 0000000000..82d144dd2c
--- /dev/null
+++ b/c/src/lib/libc/fstat.c
@@ -0,0 +1,94 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "libio_.h"
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if (rtems_file_descriptor_type(fd)) {
+ switch (rtems_file_descriptor_type (fd)) {
+ case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
+ break;
+
+ case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
+#if !defined(__GO32__)
+ sbuf->st_mode = S_IFSOCK;
+ break;
+#endif
+
+ default:
+ set_errno_and_return_minus_one( EBADF );
+ }
+ }
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fstat)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/c/src/lib/libc/fsync.c b/c/src/lib/libc/fsync.c
new file mode 100644
index 0000000000..a5ed1e99e7
--- /dev/null
+++ b/c/src/lib/libc/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fsync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fsync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync)( iop );
+}
diff --git a/c/src/lib/libc/ftruncate.c b/c/src/lib/libc/ftruncate.c
new file mode 100644
index 0000000000..7fb2286531
--- /dev/null
+++ b/c/src/lib/libc/ftruncate.c
@@ -0,0 +1,60 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate)( iop, length );
+}
+
diff --git a/c/src/lib/libc/getdents.c b/c/src/lib/libc/getdents.c
index 9b16d82409..91631843b7 100644
--- a/c/src/lib/libc/getdents.c
+++ b/c/src/lib/libc/getdents.c
@@ -1,14 +1,59 @@
/*
- * Just enough to make newlib return an error.
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
+#include <errno.h>
+
+#include "libio_.h"
+
int getdents(
- int fd,
- void *buf,
- int len
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
)
{
- return -1;
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read)( iop, dd_buf, dd_len );
}
diff --git a/c/src/lib/libc/hosterr.c b/c/src/lib/libc/hosterr.c
index a55e4a7e84..6c0308df3b 100644
--- a/c/src/lib/libc/hosterr.c
+++ b/c/src/lib/libc/hosterr.c
@@ -13,31 +13,36 @@
*/
#include <rtems.h>
+#if defined(RTEMS_UNIX)
#include <errno.h>
-int host_errno(void);
+int host_errno( void );
/*
- * copy host errno, if any to thread aware errno, if any
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
*/
-void fix_syscall_errno(void)
+void fix_syscall_errno( void )
{
- errno = host_errno();
+ errno = host_errno();
}
/*
- * Get the host system errno, if any
- * When using newlib (or possibly other libc's) on top of UNIX
- * the errno returned by system calls may be unavailable due
- * to trickery of making errno thread aware.
- * This provides a kludge of getting at it.
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
*/
#undef errno
extern int errno;
int host_errno(void)
{
- return errno;
+ return errno;
}
-
+#endif
diff --git a/c/src/lib/libc/imfs.h b/c/src/lib/libc/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/lib/libc/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libc/imfs_chown.c b/c/src/lib/libc/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/lib/libc/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_creat.c b/c/src/lib/libc/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/lib/libc/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/lib/libc/imfs_debug.c b/c/src/lib/libc/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/lib/libc/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/lib/libc/imfs_directory.c b/c/src/lib/libc/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/lib/libc/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/lib/libc/imfs_eval.c b/c/src/lib/libc/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/lib/libc/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/lib/libc/imfs_fchmod.c b/c/src/lib/libc/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/lib/libc/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_free.c b/c/src/lib/libc/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/lib/libc/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_getchild.c b/c/src/lib/libc/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/lib/libc/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_gtkn.c b/c/src/lib/libc/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/lib/libc/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/lib/libc/imfs_handlers.c b/c/src/lib/libc/imfs_handlers.c
new file mode 100644
index 0000000000..cd9cdcb435
--- /dev/null
+++ b/c/src/lib/libc/imfs_handlers.c
@@ -0,0 +1,93 @@
+/*
+ * Operations Tables for the IMFS
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Set of operations handlers for operations on memfile entities.
+ */
+
+rtems_filesystem_file_handlers_r memfile_handlers = {
+ memfile_open,
+ memfile_close,
+ memfile_read,
+ memfile_write,
+ memfile_ioctl,
+ memfile_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ memfile_ftruncate,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Set of operations handlers for operations on directories.
+ */
+
+rtems_filesystem_file_handlers_r dir_handlers = {
+ imfs_dir_open,
+ imfs_dir_close,
+ imfs_dir_read,
+ NULL,
+ NULL,
+ imfs_dir_lseek,
+ imfs_dir_fstat,
+ IMFS_fchmod,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Handler table for IMFS device nodes
+ */
+
+rtems_filesystem_file_handlers_r device_handlers = {
+ device_open,
+ device_close,
+ device_read,
+ device_write,
+ device_ioctl,
+ device_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Set of null operations handlers.
+ */
+
+rtems_filesystem_file_handlers_r null_handlers = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/c/src/lib/libc/imfs_init.c b/c/src/lib/libc/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/lib/libc/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/lib/libc/imfs_initsupp.c b/c/src/lib/libc/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/lib/libc/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/lib/libc/imfs_link.c b/c/src/lib/libc/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/lib/libc/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_mknod.c b/c/src/lib/libc/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/lib/libc/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_mount.c b/c/src/lib/libc/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/lib/libc/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_ntype.c b/c/src/lib/libc/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/lib/libc/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/lib/libc/imfs_readlink.c b/c/src/lib/libc/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/lib/libc/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/lib/libc/imfs_rmnod.c b/c/src/lib/libc/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/lib/libc/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/lib/libc/imfs_stat.c b/c/src/lib/libc/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/lib/libc/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_symlink.c b/c/src/lib/libc/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/lib/libc/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/lib/libc/imfs_unlink.c b/c/src/lib/libc/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/lib/libc/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/lib/libc/imfs_unmount.c b/c/src/lib/libc/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/lib/libc/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_utime.c b/c/src/lib/libc/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/lib/libc/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/internal.h b/c/src/lib/libc/internal.h
deleted file mode 100644
index 75b9f29633..0000000000
--- a/c/src/lib/libc/internal.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* internal.h
- *
- * This include file contains internal information
- * for the RTEMS C library support which is needed across
- * files.
- *
- * COPYRIGHT (c) 1989-1998.
- * On-Line Applications Research Corporation (OAR).
- * Copyright assigned to U.S. Government, 1994.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
- * $Id$
- */
-
-#ifndef __INTERNAL_LIBC_h
-#define __INTERNAL_LIBC_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void MY_task_set_note(
- rtems_tcb *tcb,
- rtems_unsigned32 notepad,
- rtems_unsigned32 note
-);
-
-rtems_unsigned32 MY_task_get_note(
- rtems_tcb *tcb,
- rtems_unsigned32 notepad
-);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-/* end of include file */
diff --git a/c/src/lib/libc/ioctl.c b/c/src/lib/libc/ioctl.c
new file mode 100644
index 0000000000..0aaf0379ae
--- /dev/null
+++ b/c/src/lib/libc/ioctl.c
@@ -0,0 +1,57 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int ioctl(
+ int fd,
+ unsigned32 command,
+ void * buffer
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_ioctl_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, command, buffer );
+ }
+
+ /*
+ * Now process the ioctl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->ioctl )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/c/src/lib/libc/ioman.c b/c/src/lib/libc/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/lib/libc/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/c/src/lib/libc/libio.c b/c/src/lib/libc/libio.c
index 12682c1190..e63a4626d4 100644
--- a/c/src/lib/libc/libio.c
+++ b/c/src/lib/libc/libio.c
@@ -1,524 +1,295 @@
/*
- * Provide UNIX/POSIX-like io system calls for RTEMS using the
- * RTEMS IO manager
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the low level
+ * POSIX system calls like open(), read, fstat(), etc.
+ *
+ * This provides the foundation for POSIX compliant IO system calls
+ * for RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
-#include <rtems.h>
-#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
-
-#include <stdio.h> /* O_RDONLY, et.al. */
-#include <fcntl.h> /* O_RDONLY, et.al. */
-#include <assert.h>
-
-#if ! defined(O_NDELAY)
-# if defined(solaris2)
-# define O_NDELAY O_NONBLOCK
-# elif defined(RTEMS_NEWLIB)
-# define O_NDELAY _FNBIO
-# endif
-#endif
-
-
-#include <errno.h>
-#include <string.h> /* strcmp */
-#include <unistd.h>
-#include <stdlib.h> /* calloc() */
-
-#include "libio.h" /* libio.h not pulled in by rtems */
+#include "libio_.h" /* libio_.h pulls in rtems */
/*
- * Semaphore to protect the io table
+ * Global variables used to manage the File Descriptor Table.
+ * IOP = IO Pointer.
*/
-Objects_Id rtems_libio_semaphore;
-
-#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
-#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
-
-extern unsigned32 rtems_libio_number_iops;
-rtems_libio_t *rtems_libio_iops;
-rtems_libio_t *rtems_libio_last_iop;
-
-#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
- &rtems_libio_iops[fd] : 0)
-
-#define rtems_libio_check_fd(fd) \
- do { \
- if ((unsigned32) (fd) >= rtems_libio_number_iops) \
- { \
- errno = EBADF; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_buffer(buffer) \
- do { \
- if ((buffer) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_count(count) \
- do { \
- if ((count) == 0) \
- { \
- return 0; \
- } \
- } while (0)
-
-#define rtems_libio_check_permissions(iop, flag) \
- do { \
- if (((iop)->flags & (flag)) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
+rtems_id rtems_libio_semaphore;
+rtems_libio_t *rtems_libio_iops;
+rtems_libio_t *rtems_libio_last_iop;
+rtems_libio_handler_t rtems_libio_handlers[15];
/*
- * External I/O handlers
- *
- * Space for all possible handlers is preallocated
- * to speed up dispatch to external handlers.
+ * rtems_register_libio_handler
+ *
+ * This function registers an external IO handler set. This lets
+ * other subsystems have their own versions of many of the system
+ * calls. For example, the networking code registers handlers which
+ * map the system calls for read() and write() to socket calls.
+ *
*/
-static rtems_libio_handler_t handlers[15];
-
-void
-rtems_register_libio_handler(
- int handler_flag,
- const rtems_libio_handler_t *handler
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
)
{
- int handler_index = rtems_file_descriptor_type_index(handler_flag);
+ int handler_index = rtems_file_descriptor_type_index( handler_flag );
+
if ((handler_index < 0) || (handler_index >= 15))
rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
- handlers[handler_index] = *handler;
-}
-
-/*
- * Called by bsp startup code to init the libio area.
- */
-void
-rtems_libio_init(void)
-{
- rtems_status_code rc;
-
- if (rtems_libio_number_iops > 0)
- {
- rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
- sizeof(rtems_libio_t));
- if (rtems_libio_iops == NULL)
- rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
-
- rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
- }
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_SEM,
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &rtems_libio_semaphore
- );
- if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_libio_handlers[handler_index] = *handler;
}
/*
- * Convert RTEMS status to a UNIX errno
+ * rtems_libio_init
+ *
+ * Called by BSP startup code to initialize the libio subsystem.
*/
-rtems_assoc_t errno_assoc[] = {
- { "OK", RTEMS_SUCCESSFUL, 0 },
- { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY },
- { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL },
- { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS },
- { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT },
- { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM },
- { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV },
- { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF},
- { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM},
- { "IO ERROR", RTEMS_IO_ERROR, EIO},
- { 0, 0, 0 },
-};
-
-static unsigned32
-rtems_libio_errno(rtems_status_code code)
+void rtems_libio_init( void )
{
- int rc;
-
- if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
- {
- errno = rc;
- return -1;
- }
- return -1;
+ rtems_status_code rc;
+
+ /*
+ * Allocate memory for the IOP Table
+ */
+
+ if ( rtems_libio_number_iops > 0 ) {
+ rtems_libio_iops =
+ (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t));
+
+ if (rtems_libio_iops == NULL)
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+
+ rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
+ }
+
+ /*
+ * Create the binary semaphore used to provide mutual exclusion
+ * on the IOP Table.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_SEM,
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_libio_semaphore
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ rtems_fatal_error_occurred( rc );
+
+ /*
+ * Initialize the base file system infrastructure.
+ */
+
+ rtems_filesystem_initialize();
}
/*
- * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
+ * rtems_libio_fcntl_flags
+ *
+ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
rtems_assoc_t access_modes_assoc[] = {
- { "READ", LIBIO_FLAGS_READ, O_RDONLY },
- { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
- { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
- { 0, 0, 0 },
+ { "READ", LIBIO_FLAGS_READ, O_RDONLY },
+ { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
+ { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
+ { 0, 0, 0 },
};
rtems_assoc_t status_flags_assoc[] = {
- { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
- { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
- { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
- { 0, 0, 0 },
+ { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
+ { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
+ { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
+ { 0, 0, 0 },
};
-static unsigned32
-rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+)
{
- unsigned32 flags = 0;
- unsigned32 access_modes;
+ unsigned32 flags = 0;
+ unsigned32 access_modes;
- /*
- * Access mode is a small integer
- */
-
- access_modes = fcntl_flags & O_ACCMODE;
- fcntl_flags &= ~O_ACCMODE;
- flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
+ /*
+ * Access mode is a small integer
+ */
+
+ access_modes = fcntl_flags & O_ACCMODE;
+ fcntl_flags &= ~O_ACCMODE;
+ flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
- /*
- * Everything else is single bits
- */
+ /*
+ * Everything else is single bits
+ */
- flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
- return flags;
+ flags |=
+ rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ return flags;
}
+/*
+ * rtems_libio_allocate
+ *
+ * This routine searches the IOP Table for an unused entry. If it
+ * finds one, it returns it. Otherwise, it returns NULL.
+ */
-static rtems_libio_t *
-rtems_libio_allocate(void)
+rtems_libio_t *rtems_libio_allocate( void )
{
- rtems_libio_t *iop;
- rtems_status_code rc;
-
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
- if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
- {
- /*
- * Got one; create a semaphore for it
- */
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &iop->sem
- );
- if (rc != RTEMS_SUCCESSFUL)
- goto failed;
-
- iop->flags = LIBIO_FLAGS_OPEN;
- goto done;
- }
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
+ if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
+ /*
+ * Got an IOP -- create a semaphore for it.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &iop->sem
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ goto failed;
+ iop->flags = LIBIO_FLAGS_OPEN;
+ goto done;
+ }
+
failed:
- iop = 0;
-
+ iop = 0;
+
done:
- rtems_semaphore_release(rtems_libio_semaphore);
- return iop;
+ rtems_semaphore_release( rtems_libio_semaphore );
+ return iop;
}
-static void
-rtems_libio_free(rtems_libio_t *iop)
-{
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- if (iop->sem)
- rtems_semaphore_delete(iop->sem);
- (void) memset(iop, 0, sizeof(*iop));
-
- rtems_semaphore_release(rtems_libio_semaphore);
-}
+/*
+ * rtems_libio_free
+ *
+ * This routine frees the resources associated with an IOP (file descriptor)
+ * and clears the slot in the IOP Table.
+ */
-int
-__rtems_open(
- const char *pathname,
- unsigned32 flag,
- unsigned32 mode)
+void rtems_libio_free(
+ rtems_libio_t *iop
+)
{
- rtems_status_code rc;
- rtems_libio_t *iop = 0;
- rtems_driver_name_t *np;
- rtems_libio_open_close_args_t args;
-
- /*
- * Additional external I/O handlers would be supported by
- * adding code to pick apart the pathname appropriately.
- * The networking code does not require changes here since
- * network file descriptors are obtained using socket(), not
- * open().
- */
-
- if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
- goto done;
-
- iop = rtems_libio_allocate();
- if (iop == 0)
- {
- rc = RTEMS_TOO_MANY;
- goto done;
- }
-
- iop->driver = np;
- iop->pathname = (char *) pathname;
- iop->flags |= rtems_libio_fcntl_flags(flag);
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.flags = iop->flags;
- args.mode = mode;
+ if (iop->sem)
+ rtems_semaphore_delete(iop->sem);
- rc = rtems_io_open(np->major, np->minor, (void *) &args);
-
-done:
-
- if (rc != RTEMS_SUCCESSFUL)
- {
- if (iop)
- rtems_libio_free(iop);
- return rtems_libio_errno(rc);
- }
-
- return iop - rtems_libio_iops;
-}
-
-int
-__rtems_close(
- int fd
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_open_close_args_t args;
- int status;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].close;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- status = (*fp)(fd);
- return status;
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+ (void) memset(iop, 0, sizeof(*iop));
- np = iop->driver;
-
- args.iop = iop;
- args.flags = 0;
- args.mode = 0;
-
- rc = rtems_io_close(np->major, np->minor, (void *) &args);
+ rtems_semaphore_release( rtems_libio_semaphore );
+}
- rtems_libio_free(iop);
+/*
+ * rtems_libio_is_open_files_in_fs
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * are any active file descriptors that refer to the atleast one node in the
+ * file system that we are trying to dismount.
+ *
+ * If there is at least one node in the file system referenced by the mount
+ * table entry a 1 is returned, otherwise a 0 is returned.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
- return 0;
-}
-
-int
-__rtems_read(
- int fd,
- void * buffer,
- unsigned32 count
- )
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t * fs_mt_entry
+)
{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].read;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+ rtems_libio_t *iop;
+ int result = 0;
- np = iop->driver;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
+ /*
+ * Look for any active file descriptor entry.
+ */
- rc = rtems_io_read(np->major, np->minor, (void *) &args);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- iop->offset += args.bytes_moved;
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
- return args.bytes_moved;
-}
-
-int
-__rtems_write(
- int fd,
- const void *buffer,
- unsigned32 count
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, const void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].write;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
+ if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
+ result = 1;
+ break;
+ }
}
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
-
- np = iop->driver;
-
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = (void *) buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
-
- rc = rtems_io_write(np->major, np->minor, (void *) &args);
+ }
- iop->offset += args.bytes_moved;
+ rtems_semaphore_release( rtems_libio_semaphore );
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
-
- return args.bytes_moved;
+ return result;
}
-int
-__rtems_ioctl(
- int fd,
- unsigned32 command,
- void * buffer)
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_ioctl_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, unsigned32 command, void *buffer);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, command, buffer);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+/*
+ * rtems_libio_is_file_open
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * given file refers to an active file descriptor.
+ *
+ * If the given file is open a 1 is returned, otherwise a 0 is returned.
+ */
- np = iop->driver;
+int rtems_libio_is_file_open(
+ void *node_access
+)
+{
+ rtems_libio_t *iop;
+ int result=0;
- args.iop = iop;
- args.command = command;
- args.buffer = buffer;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- rc = rtems_io_control(np->major, np->minor, (void *) &args);
+ /*
+ * Look for any active file descriptor entry.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- return args.ioctl_return;
-}
-
-/*
- * internal only??
- */
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
-int
-__rtems_lseek(
- int fd,
- rtems_libio_offset_t offset,
- int whence
- )
-{
- rtems_libio_t *iop;
+ if ( iop->pathinfo.node_access == node_access ) {
+ result = 1;
+ break;
+ }
+ }
+ }
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_semaphore_release( rtems_libio_semaphore );
- fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, offset, whence);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
-
- switch (whence)
- {
- case SEEK_SET:
- iop->offset = offset;
- break;
-
- case SEEK_CUR:
- iop->offset += offset;
- break;
-
- case SEEK_END:
- iop->offset = iop->size - offset;
- break;
-
- default:
- errno = EINVAL;
- return -1;
- }
- return 0;
+ return result;
}
diff --git a/c/src/lib/libc/libio.h b/c/src/lib/libc/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/lib/libc/libio.h
+++ b/c/src/lib/libc/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/lib/libc/libio_.h b/c/src/lib/libc/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/lib/libc/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/lib/libc/link.c b/c/src/lib/libc/link.c
new file mode 100644
index 0000000000..1cee54d0bf
--- /dev/null
+++ b/c/src/lib/libc/link.c
@@ -0,0 +1,60 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+ result = (*parent_loc.ops->evalformake)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 )
+ set_errno_and_return_minus_one( result );
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry )
+ set_errno_and_return_minus_one( EXDEV );
+
+ if ( !parent_loc.ops->link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start );
+}
diff --git a/c/src/lib/libc/lseek.c b/c/src/lib/libc/lseek.c
new file mode 100644
index 0000000000..514f8cd912
--- /dev/null
+++ b/c/src/lib/libc/lseek.c
@@ -0,0 +1,93 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+
+#include "libio_.h"
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_lseek_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, offset, whence );
+ }
+
+ /*
+ * Now process the lseek().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ switch ( whence ) {
+ case SEEK_SET:
+ iop->offset = offset;
+ break;
+
+ case SEEK_CUR:
+ iop->offset += offset;
+ break;
+
+ case SEEK_END:
+ iop->offset = iop->size - offset;
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ( !iop->handlers->lseek )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->lseek)( iop, offset, whence );
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
+
diff --git a/c/src/lib/libc/malloc.c b/c/src/lib/libc/malloc.c
index fac38585a7..f164e45f6c 100644
--- a/c/src/lib/libc/malloc.c
+++ b/c/src/lib/libc/malloc.c
@@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize(
#ifdef MALLOC_STATS
/* zero all the stats */
- (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats));
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
#endif
MSBUMP(space_available, length);
@@ -220,9 +220,11 @@ void *malloc(
{
unsigned32 actual_size;
unsigned32 current_depth;
- status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size);
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
MSBUMP(lifetime_allocated, actual_size);
- current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
if (current_depth > rtems_malloc_stats.max_depth)
rtems_malloc_stats.max_depth = current_depth;
}
@@ -335,10 +337,12 @@ void free(
void malloc_dump(void)
{
- unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
printf("Malloc stats\n");
- printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
(unsigned int) rtems_malloc_stats.space_available / 1024,
(unsigned int) allocated / 1024,
/* avoid float! */
diff --git a/c/src/lib/libc/memfile.c b/c/src/lib/libc/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/lib/libc/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/lib/libc/mkdir.c b/c/src/lib/libc/mkdir.c
new file mode 100644
index 0000000000..18fc7171c7
--- /dev/null
+++ b/c/src/lib/libc/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
+
diff --git a/c/src/lib/libc/mkfifo.c b/c/src/lib/libc/mkfifo.c
new file mode 100644
index 0000000000..6b3ece5650
--- /dev/null
+++ b/c/src/lib/libc/mkfifo.c
@@ -0,0 +1,25 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/c/src/lib/libc/mknod.c b/c/src/lib/libc/mknod.c
new file mode 100644
index 0000000000..4f83321ecd
--- /dev/null
+++ b/c/src/lib/libc/mknod.c
@@ -0,0 +1,60 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc );
+}
diff --git a/c/src/lib/libc/mount.c b/c/src/lib/libc/mount.c
new file mode 100644
index 0000000000..fa8cebc3f9
--- /dev/null
+++ b/c/src/lib/libc/mount.c
@@ -0,0 +1,299 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+/*
+ * XXX
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+);
+
+int init_fs_mount_table( void );
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_options_t options;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Are the file system options valid?
+ */
+
+ options = get_file_system_options( fsoptions );
+ if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Is the file system type valid?
+ */
+
+ if ( fs_ops == NULL ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) );
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if( device )
+ sprintf( temp_mt_entry->dev, "%s", device );
+ else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+ if ( rtems_filesystem_evaluate_path(
+ mount_point,
+ RTEMS_LIBIO_PERMS_RWX,
+ &temp_loc ,
+ TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry
+ */
+
+ temp_mt_entry->mt_point_node.node_access = temp_loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = temp_loc.handlers;
+ temp_mt_entry->mt_point_node.ops = temp_loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !temp_loc.ops->mount ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( temp_loc.ops->mount( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ }
+ else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( !fs_ops->fsmount_me ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( fs_ops->fsmount_me( temp_mt_entry ) )
+ goto cleanup_and_bail;
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * get_file_system_options
+ *
+ * This routine will determine is the text string that represents the options
+ * that are to be used to mount the file system are actually valid. If the
+ * options are valid the appropriate file system options type will be returned
+ * to the calling routine.
+ */
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+)
+{
+ if ( strcmp( "RO", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_ONLY;
+ if ( strcmp( "RW", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_WRITE_ONLY;
+ else
+ return RTEMS_FILESYSTEM_BAD_OPTIONS;
+}
+
+
+
+/*
+ * search_mt_for_mount_point
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_point_node to the node describing the selected
+ * mount point.. If any of the mount table file system mount point nodes
+ * match the new file system selected mount point node, we are attempting
+ * to mount the new file system onto a node that already has a file system
+ * mounted to it. This is not a permitted operation.
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_point_node.node_access ==
+ location_of_mount_point->node_access )
+ return FOUND;
+ }
+ return NOT_FOUND;
+}
+
diff --git a/c/src/lib/libc/newlibc.c b/c/src/lib/libc/newlibc.c
index a6acc1c8d7..bea592a46e 100644
--- a/c/src/lib/libc/newlibc.c
+++ b/c/src/lib/libc/newlibc.c
@@ -1,21 +1,14 @@
-
/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
* COPYRIGHT (c) 1994 by Division Incorporated
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
- * Description:
- * Implementation of hooks for the CYGNUS newlib libc
- * These hooks set things up so that:
- * '_REENT' is switched at task switch time.
- *
- *
- * TODO:
- *
- * NOTE:
- *
* $Id$
*
*/
@@ -47,7 +40,21 @@
#include <stdio.h>
#endif
-#include "internal.h"
+/*
+ * Private routines
+ */
+
+void MY_task_set_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad,
+ rtems_unsigned32 note
+);
+
+rtems_unsigned32 MY_task_get_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad
+);
+
#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
@@ -304,7 +311,7 @@ libc_init(int reentrant)
rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
&libc_extension, &extension_id);
if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_fatal_error_occurred( rc );
libc_reentrant = reentrant;
}
@@ -353,11 +360,14 @@ int get_errno()
/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
#if !defined(RTEMS_UNIX) && !defined(_AM29K)
+#if !defined(pc386)
void _exit(int status)
{
libc_wrapup(); /* Why? XXX */
rtems_shutdown_executive(status);
}
+#endif
+
#else
void exit(int status)
@@ -426,4 +436,46 @@ unsigned int sleep(
#endif
+/*
+ * Newlib Interface Support
+ *
+ * Routines to Access Internal RTEMS Resources without violating
+ * kernel visibility.
+ *
+ */
+
+void MY_task_set_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad,
+ unsigned32 note
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( api )
+ api->Notepads[ notepad ] = note;
+}
+
+
+unsigned32 MY_task_get_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ return api->Notepads[ notepad ];
+}
+
+void *MY_CPU_Context_FP_start(
+ void *base,
+ unsigned32 offset
+)
+{
+ return _CPU_Context_Fp_start( base, offset );
+}
#endif
diff --git a/c/src/lib/libc/newlibif.c b/c/src/lib/libc/newlibif.c
deleted file mode 100644
index 8b995fed92..0000000000
--- a/c/src/lib/libc/newlibif.c
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/*
- * This file contains the glue which maps newlib system calls onto their
- * RTEMS implementations. This formerly was in the file
- * libgloss/rtems/iface.c which was installed as rtems.o. Merging this
- * into the RTEMS source tree minimizes the files which must be linked
- * to build an rtems application.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <reent.h>
-
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-int
-read(int fd,
- char *buf,
- int nbytes)
-{
- return __rtems_read(fd, buf, nbytes);
-}
-
-int
-write(int fd,
- char *buf,
- int nbytes)
-{
- return __rtems_write(fd, buf, nbytes);
-}
-
-int
-open(char *buf,
- int flags,
- int mode)
-{
- return __rtems_open(buf, flags, mode);
-}
-
-int
-close(int fd)
-{
- return __rtems_close(fd);
-}
-
-/*
- * lseek -- move read/write pointer. Since a serial port
- * is non-seekable, we return an error.
- */
-off_t
-lseek(int fd,
- off_t offset,
- int whence)
-{
- return __rtems_lseek(fd, offset, whence);
-}
-
-/*
- * fstat -- get status of a file. Since we have no file
- * system, we just return an error.
- */
-int
-fstat(int fd,
- struct stat *buf)
-{
- return __rtems_fstat(fd, buf);
-}
-
-/*
- * getpid and kill are provided directly by rtems
- */
-
-/*
- * ioctl -- IO control
- */
-
-int
-ioctl(int fd, int request, void *argp)
-{
- return __rtems_ioctl(fd,request,argp);
-}
-
-#endif
diff --git a/c/src/lib/libc/newlibifr.c b/c/src/lib/libc/newlibifr.c
deleted file mode 100644
index 5d870c91a6..0000000000
--- a/c/src/lib/libc/newlibifr.c
+++ /dev/null
@@ -1,103 +0,0 @@
-
-/*
- * This file contains the glue which maps newlib system calls onto their
- * RTEMS implementations. This formerly was in the file
- * libgloss/rtems/iface.c which was installed as rtems.o. Merging this
- * into the RTEMS source tree minimizes the files which must be linked
- * to build an rtems application.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <reent.h>
-
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-_ssize_t _read_r(
- struct _reent *ptr,
- int fd,
- void *buf,
- size_t nbytes
-)
-{
- return __rtems_read(fd, buf, nbytes);
-}
-
-long _write_r(
- struct _reent *ptr,
- int fd,
- const void *buf,
- size_t nbytes
-)
-{
- return __rtems_write(fd, buf, nbytes);
-}
-
-int _open_r(
- struct _reent *ptr,
- const char *buf,
- int flags,
- int mode
-)
-{
- return __rtems_open(buf, flags, mode);
-}
-
-int _close_r(
- struct _reent *ptr,
- int fd
-)
-{
- return __rtems_close(fd);
-}
-
-off_t _lseek_r(
- struct _reent *ptr,
- int fd,
- off_t offset,
- int whence
-)
-{
- return __rtems_lseek(fd, offset, whence);
-}
-
-int _stat_r(
- struct _reent *ptr,
- const char *path,
- struct stat *buf
-)
-{
- return stat(path, buf);
-}
-
-int _fstat_r(
- struct _reent *ptr,
- int fd,
- struct stat *buf
-)
-{
- return __rtems_fstat(fd, buf);
-}
-
-pid_t _getpid_r(struct _reent *ptr)
-{
- pid_t __getpid();
- return __getpid();
-}
-
-int _kill_r( struct _reent *ptr, pid_t pid, int sig )
-{
- int __kill();
- return __kill(pid, sig);
-}
-#endif
diff --git a/c/src/lib/libc/no_libc.c b/c/src/lib/libc/no_libc.c
index 5a58ba761c..4bd02c4b27 100644
--- a/c/src/lib/libc/no_libc.c
+++ b/c/src/lib/libc/no_libc.c
@@ -1,6 +1,4 @@
-
-/* no_libc.h
- *
+/*
* This file contains stubs for the reentrancy hooks when
* an unknown C library is used.
*
@@ -17,15 +15,15 @@
#include <rtems.h>
-#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
#include "libcsupport.h"
-#include "internal.h"
#include <stdlib.h> /* for free() */
-void
-libc_init(int reentrant)
+void libc_init(
+ int reentrant
+)
{
}
@@ -34,11 +32,15 @@ void libc_suspend_main(void)
}
-void libc_global_exit(rtems_unsigned32 code)
+void libc_global_exit(
+ rtems_unsigned32 code
+)
{
}
-void _exit(int status)
+void _exit(
+ int status
+)
{
}
diff --git a/c/src/lib/libc/open.c b/c/src/lib/libc/open.c
new file mode 100644
index 0000000000..4cdf5acf35
--- /dev/null
+++ b/c/src/lib/libc/open.c
@@ -0,0 +1,202 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and eitehr the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * Additional external I/O handlers would be supported by adding
+ * code to pick apart the pathname appropriately. The networking
+ * code does not require changes here since network file
+ * descriptors are obtained using socket(), not open().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+
+ status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ goto done;
+ }
+
+ /*
+ * Fill in the file control block based on the temp_loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = temp_loc.handlers;
+ iop->file_info = temp_loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = temp_loc;
+
+ if ( !iop->handlers->open ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ set_errno_and_return_minus_one( rc );
+ }
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/c/src/lib/libc/opendir.c b/c/src/lib/libc/opendir.c
index e303eb28e5..f0e9488684 100644
--- a/c/src/lib/libc/opendir.c
+++ b/c/src/lib/libc/opendir.c
@@ -1,17 +1,85 @@
/*
* opendir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
-DIR *opendir(
- const char *name
-)
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
{
- return NULL;
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
}
diff --git a/c/src/lib/libc/pathconf.c b/c/src/lib/libc/pathconf.c
new file mode 100644
index 0000000000..e19d1329f4
--- /dev/null
+++ b/c/src/lib/libc/pathconf.c
@@ -0,0 +1,38 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/c/src/lib/libc/pipe.c b/c/src/lib/libc/pipe.c
new file mode 100644
index 0000000000..35dcf627bb
--- /dev/null
+++ b/c/src/lib/libc/pipe.c
@@ -0,0 +1,23 @@
+/*
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+int pipe(
+ int filsdes[2]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/c/src/lib/libc/read.c b/c/src/lib/libc/read.c
new file mode 100644
index 0000000000..150fe675ab
--- /dev/null
+++ b/c/src/lib/libc/read.c
@@ -0,0 +1,84 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int read(
+ int fd,
+ void *buffer,
+ unsigned32 count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_read_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the read().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/lib/libc/readdir.c b/c/src/lib/libc/readdir.c
index d592a62b99..f950d56171 100644
--- a/c/src/lib/libc/readdir.c
+++ b/c/src/lib/libc/readdir.c
@@ -1,14 +1,77 @@
/*
* readdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
-struct dirent *readdir(
- register DIR *dirp
-)
-{
- return NULL;
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
}
diff --git a/c/src/lib/libc/readlink.c b/c/src/lib/libc/readlink.c
new file mode 100644
index 0000000000..22de51e88f
--- /dev/null
+++ b/c/src/lib/libc/readlink.c
@@ -0,0 +1,43 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if (!buf)
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( !loc.ops->readlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->readlink)( &loc, buf, bufsize );
+}
diff --git a/c/src/lib/libc/rewinddir.c b/c/src/lib/libc/rewinddir.c
index c85e6fd4d0..04313a6042 100644
--- a/c/src/lib/libc/rewinddir.c
+++ b/c/src/lib/libc/rewinddir.c
@@ -1,7 +1,14 @@
/*
* rewinddir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/types.h>
@@ -15,6 +22,14 @@ void rewinddir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
+
}
diff --git a/c/src/lib/libc/rmdir.c b/c/src/lib/libc/rmdir.c
new file mode 100644
index 0000000000..6c0331087f
--- /dev/null
+++ b/c/src/lib/libc/rmdir.c
@@ -0,0 +1,56 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libio_.h"
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.ops->rmnod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->rmnod)( &loc );
+}
diff --git a/c/src/lib/libc/scandir.c b/c/src/lib/libc/scandir.c
index 380415dd97..9ba1cb7bec 100644
--- a/c/src/lib/libc/scandir.c
+++ b/c/src/lib/libc/scandir.c
@@ -1,7 +1,50 @@
/*
* scandir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
@@ -9,15 +52,98 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-int scandir(
- const char *dirname,
- struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*dcomp)(const void *, const void *)
-)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d, *p, **names;
+ register size_t nitems;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1);
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1); /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
{
- errno = ENOSYS;
- return -1;
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
}
diff --git a/c/src/lib/libc/seekdir.c b/c/src/lib/libc/seekdir.c
index e591adbb9f..80802b56c6 100644
--- a/c/src/lib/libc/seekdir.c
+++ b/c/src/lib/libc/seekdir.c
@@ -1,7 +1,14 @@
/*
* seekdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -12,10 +19,20 @@
#include <errno.h>
void seekdir(
- DIR *dirp,
- long loc
+ DIR *dirp,
+ long loc
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
}
diff --git a/c/src/lib/libc/stat.c b/c/src/lib/libc/stat.c
new file mode 100644
index 0000000000..8ad7e61511
--- /dev/null
+++ b/c/src/lib/libc/stat.c
@@ -0,0 +1,79 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int stat(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ return (*loc.handlers->fstat)( &loc, buf );
+}
+#endif
+
+/*
+ * _stat_r
+ *
+ * This is the Newlib dependent reentrant version of stat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _stat_r(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return stat( path, buf );
+}
+#endif
diff --git a/c/src/lib/libc/support.c b/c/src/lib/libc/support.c
deleted file mode 100644
index 85e6bb363f..0000000000
--- a/c/src/lib/libc/support.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Routines to Access Internal RTEMS Resources
- *
- * COPYRIGHT (c) 1989-1998.
- * On-Line Applications Research Corporation (OAR).
- * Copyright assigned to U.S. Government, 1994.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-
-void MY_task_set_note(
- Thread_Control *the_thread,
- unsigned32 notepad,
- unsigned32 note
-)
-{
- RTEMS_API_Control *api;
-
- api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
-
- if ( api )
- api->Notepads[ notepad ] = note;
-}
-
-
-unsigned32 MY_task_get_note(
- Thread_Control *the_thread,
- unsigned32 notepad
-)
-{
- RTEMS_API_Control *api;
-
- api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
-
- return api->Notepads[ notepad ];
-}
-
-void *MY_CPU_Context_FP_start(
- void *base,
- unsigned32 offset
-)
-{
- return _CPU_Context_Fp_start( base, offset );
-}
-
diff --git a/c/src/lib/libc/symlink.c b/c/src/lib/libc/symlink.c
new file mode 100644
index 0000000000..ca9673f51b
--- /dev/null
+++ b/c/src/lib/libc/symlink.c
@@ -0,0 +1,34 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ return (*loc.ops->symlink)( &loc, actualpath, name_start);
+}
+
diff --git a/c/src/lib/libc/syscalls.c b/c/src/lib/libc/syscalls.c
deleted file mode 100644
index e97034ddba..0000000000
--- a/c/src/lib/libc/syscalls.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * RTEMS Fake System Calls
- *
- * This file contains "fake" versions of the system call routines
- * which are reference by many libc implementations. Once a routine
- * has been implemented in terms of RTEMS services, it should be
- * taken out of this file.
- *
- * COPYRIGHT (c) 1989-1998.
- * On-Line Applications Research Corporation (OAR).
- * Copyright assigned to U.S. Government, 1994.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
- * $Id$
- *
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h> /* only for puts */
-
-#include <rtems.h>
-#include <rtems/libio.h>
-
-#ifdef RTEMS_NEWLIB
-
-int __rtems_fstat(int _fd, struct stat* _sbuf)
-{
-#ifdef HAVE_BLKSIZE
- _sbuf->st_blksize = 0;
-#endif
-
- /*
- * For now assume stdin/stdout/stderr are always a TTY line
- *
- * From Eric Norum:
- *
- * The `fix' is not complete. It still doesn't properly handle
- * file descriptors for any files/devices other than the console
- * serial lines.....
- */
- if (_fd <= 2) {
- _sbuf->st_mode = S_IFCHR;
- } else {
- switch (rtems_file_descriptor_type (_fd)) {
- case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
- _sbuf->st_mode = S_IFREG;
- break;
-
- case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
-#if !defined(__GO32__)
- _sbuf->st_mode = S_IFSOCK;
- break;
-#endif
-
- default:
- puts( "__rtems_fstat -- unknown file descriptor type" );
- assert( 0 );
- }
- }
- return 0;
-}
-
-#if !defined(RTEMS_UNIX)
-int stat( const char *path, struct stat *buf )
-{
- if ( strncmp( "/dev/", path, 5 ) ) {
- return -1;
- }
- return __rtems_fstat( 0, buf );
-}
-
-int link( const char *existing, const char *new )
-{
- /* always fail */
- return -1;
-}
-
-int unlink( const char *path )
-{
- /* always fail */
- return -1;
-}
-
-char *getcwd( char *_buf, size_t _size)
-{
-/* assert( FALSE ); */
- errno = ENOSYS;
- return 0;
-}
-#endif
-
-#endif
diff --git a/c/src/lib/libc/tcattr.c b/c/src/lib/libc/tcattr.c
deleted file mode 100644
index aaa5ff6e6e..0000000000
--- a/c/src/lib/libc/tcattr.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcgetattr and tcsetattr.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-/*
- * tcgetattr/tcsetattr -- get/set attributes of a device.
- *
- * submitted by K.Shibuya
- */
-
-int
-tcgetattr(int fd, struct termios *tp)
-{
- return __rtems_ioctl(fd,RTEMS_IO_GET_ATTRIBUTES,tp);
-}
-
-int
-tcsetattr(int fd, int opt, struct termios *tp)
-{
- if(opt != TCSANOW)
- return -1;
- return __rtems_ioctl(fd,RTEMS_IO_SET_ATTRIBUTES,tp);
-}
-
-#endif
diff --git a/c/src/lib/libc/tcdrain.c b/c/src/lib/libc/tcdrain.c
index 585871cc90..c2749a90e1 100644
--- a/c/src/lib/libc/tcdrain.c
+++ b/c/src/lib/libc/tcdrain.c
@@ -1,9 +1,15 @@
/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcdrain.
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
+ * $Id$
*/
#include <rtems.h>
@@ -13,14 +19,15 @@
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>
+#include <sys/ioctl.h>
-#include "internal.h"
#include "libio.h"
-int
-tcdrain(int fd)
+int tcdrain(
+ int fd
+)
{
- return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0);
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
}
#endif
diff --git a/c/src/lib/libc/tcgetattr.c b/c/src/lib/libc/tcgetattr.c
new file mode 100644
index 0000000000..2d3e4d7e3c
--- /dev/null
+++ b/c/src/lib/libc/tcgetattr.c
@@ -0,0 +1,33 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/lib/libc/tcsetattr.c b/c/src/lib/libc/tcsetattr.c
new file mode 100644
index 0000000000..c0ed509a0f
--- /dev/null
+++ b/c/src/lib/libc/tcsetattr.c
@@ -0,0 +1,38 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+#include "libio_.h"
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ if ( opt != TCSANOW )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/lib/libc/telldir.c b/c/src/lib/libc/telldir.c
index eee8d925ec..cea6cc08cb 100644
--- a/c/src/lib/libc/telldir.c
+++ b/c/src/lib/libc/telldir.c
@@ -1,7 +1,14 @@
/*
* telldir() - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -9,15 +16,24 @@
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
-#include <rtems.h>
-#include "libio.h"
+#include "libio_.h"
+
long telldir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ rtems_libio_t *iop;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
}
diff --git a/c/src/lib/libc/truncate.c b/c/src/lib/libc/truncate.c
new file mode 100644
index 0000000000..145e596654
--- /dev/null
+++ b/c/src/lib/libc/truncate.c
@@ -0,0 +1,41 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
+
diff --git a/c/src/lib/libc/umask.c b/c/src/lib/libc/umask.c
new file mode 100644
index 0000000000..35229a30a1
--- /dev/null
+++ b/c/src/lib/libc/umask.c
@@ -0,0 +1,30 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libio_.h"
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/c/src/lib/libc/unixlibc.c b/c/src/lib/libc/unixlibc.c
index 3e757e313d..a581d95534 100644
--- a/c/src/lib/libc/unixlibc.c
+++ b/c/src/lib/libc/unixlibc.c
@@ -1,5 +1,15 @@
/*
* $Id$
+ * UNIX Port C Library Support
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <rtems.h>
diff --git a/c/src/lib/libc/unlink.c b/c/src/lib/libc/unlink.c
new file mode 100644
index 0000000000..d4a5520bcb
--- /dev/null
+++ b/c/src/lib/libc/unlink.c
@@ -0,0 +1,44 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ if ( !loc.ops->unlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->unlink)( &loc );
+}
diff --git a/c/src/lib/libc/unmount.c b/c/src/lib/libc/unmount.c
new file mode 100644
index 0000000000..f50e63ff42
--- /dev/null
+++ b/c/src/lib/libc/unmount.c
@@ -0,0 +1,214 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+);
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a mount_path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *mount_path
+)
+{
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_mount_table_entry_t temp_mt_entry;
+ int result;
+
+ /*
+ * Are there any file systems below the mount_path specified
+ */
+
+ status = file_systems_below_this_mountpoint(
+ mount_path,
+ &temp_loc,
+ &temp_mt_entry
+ );
+
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Is the current node reference pointing to a node in the file system
+ * we are attempting to unmount ?
+ */
+
+ if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being mounted on to do its cleanup.
+ * XXX - Did I change these correctly ??? It looks like either I did
+ * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped.
+ * XXX Add to the mt_point_node unmount to set the mt_entry back to null
+ * XXX I will step off in space when evaluating past the end of the node.
+ */
+
+ if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Run the unmount function for the subordinate file system.
+ */
+
+ if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the file system to clean up.
+ */
+
+ result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry );
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry );
+
+ /*
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ free( temp_loc.mt_entry );
+
+ return result;
+
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+ rtems_filesystem_mount_table_entry_t *current_fs_mt_entry;
+
+ /*
+ * Is the mount_path even a valid node name in the existing tree?
+ */
+
+ if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) )
+ return -1;
+
+ /*
+ * Look for the node defined in temp_loc as a mount point in the
+ * mount table chain.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.node_access ==
+ temp_loc->node_access ) {
+ current_fs_mt_entry = the_mount_entry;
+ *temp_loc = current_fs_mt_entry->mt_fs_root;
+ goto after_real_mount_point_found;
+ }
+ }
+ set_errno_and_return_minus_one( EACCES );
+
+
+after_real_mount_point_found:
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+
+ /*
+ * Exclude the current file systems mount table entry from the test
+ */
+
+ if ( current_fs_mt_entry != the_mount_entry ) {
+ if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) {
+
+ /*
+ * There is at least one fs below the fs on the mount_path.
+ */
+ set_errno_and_return_minus_one( EBUSY );
+ }
+ }
+ }
+
+ *temp_mt_entry = *current_fs_mt_entry;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/utime.c b/c/src/lib/libc/utime.c
new file mode 100644
index 0000000000..f1a12ee1b2
--- /dev/null
+++ b/c/src/lib/libc/utime.c
@@ -0,0 +1,35 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime );
+}
diff --git a/c/src/lib/libc/write.c b/c/src/lib/libc/write.c
new file mode 100644
index 0000000000..7e0953bb90
--- /dev/null
+++ b/c/src/lib/libc/write.c
@@ -0,0 +1,92 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int write( /* XXX this should return a ssize_t */
+ int fd,
+ const void *buffer,
+ unsigned32 count /* XXX this should be a size_t */
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_write_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the write() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->write )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+long _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/lib/libchip/serial/ns16550.c b/c/src/lib/libchip/serial/ns16550.c
index 918e87bf8c..6cb0714c32 100644
--- a/c/src/lib/libchip/serial/ns16550.c
+++ b/c/src/lib/libchip/serial/ns16550.c
@@ -424,6 +424,7 @@ NS16550_STATIC int ns16550_set_attributes(
rtems_interrupt_enable(Irql);
+ return 0;
}
/*
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c
index 918e87bf8c..6cb0714c32 100644
--- a/c/src/libchip/serial/ns16550.c
+++ b/c/src/libchip/serial/ns16550.c
@@ -424,6 +424,7 @@ NS16550_STATIC int ns16550_set_attributes(
rtems_interrupt_enable(Irql);
+ return 0;
}
/*
diff --git a/c/src/libfs/src/imfs/deviceio.c b/c/src/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/libfs/src/imfs/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/libfs/src/imfs/imfs.h b/c/src/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/libfs/src/imfs/imfs_chown.c b/c/src/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_creat.c b/c/src/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/libfs/src/imfs/imfs_debug.c b/c/src/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/libfs/src/imfs/imfs_directory.c b/c/src/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_eval.c b/c/src/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_fchmod.c b/c/src/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_free.c b/c/src/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_getchild.c b/c/src/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_gtkn.c b/c/src/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/libfs/src/imfs/imfs_init.c b/c/src/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_initsupp.c b/c/src/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_link.c b/c/src/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_mknod.c b/c/src/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_mount.c b/c/src/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_ntype.c b/c/src/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/libfs/src/imfs/imfs_readlink.c b/c/src/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/libfs/src/imfs/imfs_rmnod.c b/c/src/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_stat.c b/c/src/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_symlink.c b/c/src/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_unlink.c b/c/src/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/libfs/src/imfs/imfs_unmount.c b/c/src/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_utime.c b/c/src/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/ioman.c b/c/src/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/libfs/src/imfs/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/c/src/libfs/src/imfs/memfile.c b/c/src/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/libfs/src/imfs/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/tests/sptests/spsize/size.c b/c/src/tests/sptests/spsize/size.c
index 97281c9ee3..d12ff93305 100644
--- a/c/src/tests/sptests/spsize/size.c
+++ b/c/src/tests/sptests/spsize/size.c
@@ -30,8 +30,10 @@
#include <rtems/rtems/intr.h>
#include <rtems/io.h>
#include <rtems/rtems/message.h>
+#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/rtems/mp.h>
#include <rtems/score/mpci.h>
+#endif
#include <rtems/rtems/part.h>
#include <rtems/score/priority.h>
#include <rtems/rtems/ratemon.h>
@@ -105,12 +107,22 @@
#define MPCI_RECEIVE_SERVER_STACK_SIZE 0
#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#define MP_SYSTEM_TASKS \
+ (MPCI_RECEIVE_SERVER_STACK_SIZE + \
+ sizeof(Thread_Control) + \
+ MPCI_RECEIVE_SERVER_FP)
+#else
+#define MP_SYSTEM_TASKS 0
+#endif
+
+/*
+ * Idle and the MPCI Receive Server Threads
+ */
+
#define SYSTEM_TASKS \
- (STACK_MINIMUM_SIZE + \
- MPCI_RECEIVE_SERVER_STACK_SIZE + \
- (2*sizeof(Thread_Control))) + \
- MPCI_RECEIVE_SERVER_FP + \
- SYSTEM_IDLE_FP
+ (STACK_MINIMUM_SIZE + sizeof(Thread_Control) + SYSTEM_IDLE_FP + \
+ MP_SYSTEM_TASKS)
#define rtems_unsigned32 unsigned32
diff --git a/configure b/configure
index 272e3252fb..cb87569c7c 100644
--- a/configure
+++ b/configure
@@ -1944,7 +1944,7 @@ echo "configure:1940: checking whether environment variable AR_FOR_TARGET is an
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable AR_FOR_TARGET should ether
+ Environment variable AR_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2027,7 +2027,7 @@ echo "configure:2023: checking whether environment variable AS_FOR_TARGET is an
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable AS_FOR_TARGET should ether
+ Environment variable AS_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2110,7 +2110,7 @@ echo "configure:2106: checking whether environment variable LD_FOR_TARGET is an
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable LD_FOR_TARGET should ether
+ Environment variable LD_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2193,7 +2193,7 @@ echo "configure:2189: checking whether environment variable NM_FOR_TARGET is an
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable NM_FOR_TARGET should ether
+ Environment variable NM_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2277,7 +2277,7 @@ echo "configure:2273: checking whether environment variable RANLIB_FOR_TARGET is
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable RANLIB_FOR_TARGET should ether
+ Environment variable RANLIB_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2350,7 +2350,7 @@ echo "$ac_t""$rtems_cv_AR_FOR_TARGET_S" 1>&6
else
{ echo "configure: error: ***
Can't figure out how to build a library index
- Nether ranlib nor ar -s seem to be available " 1>&2; exit 1; }
+ Neither ranlib nor ar -s seem to be available " 1>&2; exit 1; }
fi
fi
@@ -2397,7 +2397,7 @@ echo "configure:2393: checking whether environment variable OBJCOPY_FOR_TARGET i
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable OBJCOPY_FOR_TARGET should ether
+ Environment variable OBJCOPY_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2480,7 +2480,7 @@ echo "configure:2476: checking whether environment variable SIZE_FOR_TARGET is a
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable SIZE_FOR_TARGET should ether
+ Environment variable SIZE_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
@@ -2563,7 +2563,7 @@ echo "configure:2559: checking whether environment variable STRIP_FOR_TARGET is
*) # invalid for AC_PATH_PROG
echo "$ac_t"""no"" 1>&6
{ echo "configure: error: ***
- Environment variable STRIP_FOR_TARGET should ether
+ Environment variable STRIP_FOR_TARGET should either
be unset (preferred) or contain an absolute path" 1>&2; exit 1; }
;;
esac
diff --git a/cpukit/include/rtems/libio_.h b/cpukit/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/cpukit/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index dcdda85aec..76a90954b0 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include "libio.h" /* libio.h not pulled in by rtems */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/cpukit/libcsupport/src/CASES b/cpukit/libcsupport/src/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/cpukit/libcsupport/src/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/cpukit/libcsupport/src/TODO b/cpukit/libcsupport/src/TODO
new file mode 100644
index 0000000000..9d894688d9
--- /dev/null
+++ b/cpukit/libcsupport/src/TODO
@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
diff --git a/cpukit/libcsupport/src/__brk.c b/cpukit/libcsupport/src/__brk.c
index 4dab22c729..24efa93adb 100644
--- a/cpukit/libcsupport/src/__brk.c
+++ b/cpukit/libcsupport/src/__brk.c
@@ -1,10 +1,7 @@
-#if !defined(RTEMS_UNIX)
-
/*
- * RTEMS "Broken" __brk/__sbrk Implementation
- *
- * NOTE: sbrk is BSP provided.
+ * RTEMS "Broken" __brk Implementation
*
+ * NOTE: sbrk() is provided by each BSP.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,27 +15,15 @@
*/
#include <rtems.h>
+#if !defined(RTEMS_UNIX)
-#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#ifdef RTEMS_NEWLIB
-#include <reent.h>
-#endif
-#include <unistd.h>
-
-/* we use RTEMS for memory management. We don't need sbrk */
-void * __sbrk(int incr)
-{
- errno = EINVAL;
- return (void *)0;
-}
-
-int __brk( const void *endds )
+int __brk(
+ const void *endds
+)
{
errno = EINVAL;
return -1;
}
-
#endif
diff --git a/cpukit/libcsupport/src/__gettod.c b/cpukit/libcsupport/src/__gettod.c
index dc83c47ce4..16857da870 100644
--- a/cpukit/libcsupport/src/__gettod.c
+++ b/cpukit/libcsupport/src/__gettod.c
@@ -1,11 +1,5 @@
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-
-#include <rtems.h>
-
-#if !defined(RTEMS_UNIX)
/*
- * RTEMS gettimeofday Implementation
- *
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,6 +12,11 @@
* $Id$
*/
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
#ifdef RTEMS_NEWLIB
#include <sys/reent.h>
#endif
@@ -61,7 +60,7 @@ int gettimeofday(
*
* NOTE: XXX this routine should really be in the executive proper.
*/
-
+
rtems_interrupt_disable(level);
seconds = _TOD_Seconds_since_epoch;
microseconds = _TOD_Current.ticks;
@@ -86,7 +85,7 @@ int gettimeofday(
return 0;
}
-#if defined(RTEMS_NEWLIB)
+#if defined(RTEMS_NEWLIB)
/*
* "Reentrant" version
@@ -102,7 +101,7 @@ int _gettimeofday_r(
}
/*
- * "System call" version
+ * "System call" version
*/
int _gettimeofday(
diff --git a/cpukit/libcsupport/src/__sbrk.c b/cpukit/libcsupport/src/__sbrk.c
new file mode 100644
index 0000000000..b1d31467fd
--- /dev/null
+++ b/cpukit/libcsupport/src/__sbrk.c
@@ -0,0 +1,29 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/__times.c b/cpukit/libcsupport/src/__times.c
index 635bf8e062..5f7525ec5f 100644
--- a/cpukit/libcsupport/src/__times.c
+++ b/cpukit/libcsupport/src/__times.c
@@ -1,6 +1,5 @@
/*
- * RTEMS _times Implementation
- *
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -25,8 +24,8 @@ clock_t _times(
struct tms *ptms
)
{
- rtems_status_code status;
- rtems_interval ticks_since_boot;
+ rtems_status_code status;
+ rtems_interval ticks;
if ( !ptms ) {
errno = EFAULT;
@@ -34,21 +33,19 @@ clock_t _times(
}
/* "POSIX" does not seem to allow for not having a TOD */
- status = rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &ticks_since_boot
- );
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
if ( status != RTEMS_SUCCESSFUL ) {
assert( 0 );
return -1;
}
/*
- * RTEMS has no notion of system versus user time and does
- * not (as of 3.2.0) keep track of CPU usage on a per task basis.
+ * RTEMS has no notion of system versus user time and although
+ * a way to keep track of per task CPU usage was added since
+ * 3.6.0, this routine does not utilize it yet.
*/
- ptms->tms_utime = ticks_since_boot;
+ ptms->tms_utime = ticks;
ptms->tms_stime = 0;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
@@ -56,6 +53,12 @@ clock_t _times(
return 0;
}
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
clock_t times(
struct tms *ptms
)
@@ -63,12 +66,21 @@ clock_t times(
return _times( ptms );
}
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
clock_t _times_r(
struct _reent *ptr,
struct tms *ptms
)
{
- return _times(ptms);
+ return _times( ptms );
}
#endif
diff --git a/cpukit/libcsupport/src/access.c b/cpukit/libcsupport/src/access.c
new file mode 100644
index 0000000000..a8be44a9a3
--- /dev/null
+++ b/cpukit/libcsupport/src/access.c
@@ -0,0 +1,46 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c
new file mode 100644
index 0000000000..c8c23e5b43
--- /dev/null
+++ b/cpukit/libcsupport/src/base_fs.c
@@ -0,0 +1,81 @@
+/*
+ * Base file system initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_filesystem_location_info_t rtems_filesystem_current;
+rtems_filesystem_location_info_t rtems_filesystem_root;
+nlink_t rtems_filesystem_link_counts;
+
+/*
+ * Default mode for created files.
+ */
+
+mode_t rtems_filesystem_umask;
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system with one instantiation
+ * of the IMFS with a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *first_entry;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = S_IWOTH | S_IROTH;
+
+ init_fs_mount_table();
+
+ status = mount(
+ &first_entry,
+ &IMFS_ops,
+ "RW",
+ NULL,
+ NULL );
+ if( status == -1 ){
+ rtems_fatal_error_occurred( 0xABCD0002 );
+ }
+
+ rtems_filesystem_link_counts = 0;
+
+ rtems_filesystem_root = first_entry->mt_fs_root;
+
+ rtems_filesystem_current = rtems_filesystem_root;
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+}
diff --git a/cpukit/libcsupport/src/cfgetispeed.c b/cpukit/libcsupport/src/cfgetispeed.c
new file mode 100644
index 0000000000..61d97cb2f1
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetispeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfgetospeed.c b/cpukit/libcsupport/src/cfgetospeed.c
new file mode 100644
index 0000000000..8815d436e9
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetospeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfsetispeed.c b/cpukit/libcsupport/src/cfsetispeed.c
new file mode 100644
index 0000000000..37d3cd0584
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetispeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfsetospeed.c b/cpukit/libcsupport/src/cfsetospeed.c
new file mode 100644
index 0000000000..f01237103b
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetospeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c
new file mode 100644
index 0000000000..4acbc8cfe0
--- /dev/null
+++ b/cpukit/libcsupport/src/chdir.c
@@ -0,0 +1,50 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c
new file mode 100644
index 0000000000..fa57d50691
--- /dev/null
+++ b/cpukit/libcsupport/src/chmod.c
@@ -0,0 +1,40 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "libio_.h"
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.handlers->fchmod)( &loc, mode );
+}
diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c
new file mode 100644
index 0000000000..189096dcd1
--- /dev/null
+++ b/cpukit/libcsupport/src/chown.c
@@ -0,0 +1,38 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "libio_.h"
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->chown )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->chown)( &temp_loc, owner, group );
+}
diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c
new file mode 100644
index 0000000000..94ddb45c90
--- /dev/null
+++ b/cpukit/libcsupport/src/close.c
@@ -0,0 +1,70 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+ int status;
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ int (*fp)(int fd);
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+ status = (*fp)( fd );
+ return status;
+ }
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+
+ if ( !iop->handlers )
+ set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->close )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->close)( iop );
+
+ rtems_libio_free( iop );
+
+ if (rc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( rc );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/cpukit/libcsupport/src/closedir.c b/cpukit/libcsupport/src/closedir.c
index 5edb3499e6..4d948ec95b 100644
--- a/cpukit/libcsupport/src/closedir.c
+++ b/cpukit/libcsupport/src/closedir.c
@@ -1,9 +1,44 @@
/*
* closedir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <dirent.h>
@@ -11,10 +46,25 @@
#include <unistd.h>
#include <errno.h>
-int closedir(
- register DIR *dirp
-)
+
+#include "libio_.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
{
- errno = ENOSYS;
- return -1;
+ int fd;
+
+ if ( !dirp )
+ set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
}
diff --git a/cpukit/libcsupport/src/dup.c b/cpukit/libcsupport/src/dup.c
new file mode 100644
index 0000000000..c17db588a7
--- /dev/null
+++ b/cpukit/libcsupport/src/dup.c
@@ -0,0 +1,23 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/cpukit/libcsupport/src/dup2.c b/cpukit/libcsupport/src/dup2.c
new file mode 100644
index 0000000000..5653425708
--- /dev/null
+++ b/cpukit/libcsupport/src/dup2.c
@@ -0,0 +1,49 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "libio_.h"
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c
new file mode 100644
index 0000000000..bf7dd1c126
--- /dev/null
+++ b/cpukit/libcsupport/src/eval.c
@@ -0,0 +1,74 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include "libio_.h"
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( follow_link ) {
+
+ if ( !pathloc->ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ type = (*pathloc->ops->node_type)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->eval_link)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c
new file mode 100644
index 0000000000..a3ca4507ab
--- /dev/null
+++ b/cpukit/libcsupport/src/fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "libio_.h"
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fchmod().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode );
+}
+
diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c
new file mode 100644
index 0000000000..f6f33534ab
--- /dev/null
+++ b/cpukit/libcsupport/src/fcntl.c
@@ -0,0 +1,111 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include "libio_.h"
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ va_list ap;
+ rtems_libio_t *iop;
+
+ va_start( ap, cmd );
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fcntl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ /*
+ * This is how it appears that this case should work:
+ *
+ * filedes2 = va_arg( ap, int )
+ * if filedes2 is 0
+ * duplicate fd into a new descriptor
+ * else
+ * duplicate fd into specified descriptor after error checking it
+ *
+ * See dup2() in case we can eliminate stuff in there.
+ */
+ return -1;
+
+ case F_GETFD: /* get f_flags */
+ if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
+ return 1;
+ return 0;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ return 0;
+
+ case F_GETFL: /* more flags (cloexec) */
+ return -1;
+
+ case F_SETFL:
+ return -1;
+
+ case F_GETLK:
+ return -1;
+
+ case F_SETLK:
+ return -1;
+
+ case F_SETLKW:
+ return -1;
+
+ case F_SETOWN: /* for sockets. */
+ return -1;
+
+ case F_GETOWN: /* for sockets. */
+ return -1;
+
+ default:
+ break;
+ }
+ return -1;
+}
diff --git a/cpukit/libcsupport/src/fdatasync.c b/cpukit/libcsupport/src/fdatasync.c
new file mode 100644
index 0000000000..58a4c4e118
--- /dev/null
+++ b/cpukit/libcsupport/src/fdatasync.c
@@ -0,0 +1,45 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fdatasync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync)( iop );
+}
diff --git a/cpukit/libcsupport/src/fpathconf.c b/cpukit/libcsupport/src/fpathconf.c
new file mode 100644
index 0000000000..ea2377e15b
--- /dev/null
+++ b/cpukit/libcsupport/src/fpathconf.c
@@ -0,0 +1,91 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then it is an error since fpathconf() is not included in the
+ * set.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the information request.
+ */
+
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/cpukit/libcsupport/src/fstat.c b/cpukit/libcsupport/src/fstat.c
new file mode 100644
index 0000000000..82d144dd2c
--- /dev/null
+++ b/cpukit/libcsupport/src/fstat.c
@@ -0,0 +1,94 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "libio_.h"
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if (rtems_file_descriptor_type(fd)) {
+ switch (rtems_file_descriptor_type (fd)) {
+ case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
+ break;
+
+ case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
+#if !defined(__GO32__)
+ sbuf->st_mode = S_IFSOCK;
+ break;
+#endif
+
+ default:
+ set_errno_and_return_minus_one( EBADF );
+ }
+ }
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fstat)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/fsync.c b/cpukit/libcsupport/src/fsync.c
new file mode 100644
index 0000000000..a5ed1e99e7
--- /dev/null
+++ b/cpukit/libcsupport/src/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+
+#include "libio_.h"
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fsync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fsync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync)( iop );
+}
diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c
new file mode 100644
index 0000000000..7fb2286531
--- /dev/null
+++ b/cpukit/libcsupport/src/ftruncate.c
@@ -0,0 +1,60 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate)( iop, length );
+}
+
diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c
index 9b16d82409..91631843b7 100644
--- a/cpukit/libcsupport/src/getdents.c
+++ b/cpukit/libcsupport/src/getdents.c
@@ -1,14 +1,59 @@
/*
- * Just enough to make newlib return an error.
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
+#include <errno.h>
+
+#include "libio_.h"
+
int getdents(
- int fd,
- void *buf,
- int len
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
)
{
- return -1;
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read)( iop, dd_buf, dd_len );
}
diff --git a/cpukit/libcsupport/src/hosterr.c b/cpukit/libcsupport/src/hosterr.c
index a55e4a7e84..6c0308df3b 100644
--- a/cpukit/libcsupport/src/hosterr.c
+++ b/cpukit/libcsupport/src/hosterr.c
@@ -13,31 +13,36 @@
*/
#include <rtems.h>
+#if defined(RTEMS_UNIX)
#include <errno.h>
-int host_errno(void);
+int host_errno( void );
/*
- * copy host errno, if any to thread aware errno, if any
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
*/
-void fix_syscall_errno(void)
+void fix_syscall_errno( void )
{
- errno = host_errno();
+ errno = host_errno();
}
/*
- * Get the host system errno, if any
- * When using newlib (or possibly other libc's) on top of UNIX
- * the errno returned by system calls may be unavailable due
- * to trickery of making errno thread aware.
- * This provides a kludge of getting at it.
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
*/
#undef errno
extern int errno;
int host_errno(void)
{
- return errno;
+ return errno;
}
-
+#endif
diff --git a/cpukit/libcsupport/src/ioctl.c b/cpukit/libcsupport/src/ioctl.c
new file mode 100644
index 0000000000..0aaf0379ae
--- /dev/null
+++ b/cpukit/libcsupport/src/ioctl.c
@@ -0,0 +1,57 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int ioctl(
+ int fd,
+ unsigned32 command,
+ void * buffer
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_ioctl_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, command, buffer );
+ }
+
+ /*
+ * Now process the ioctl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->ioctl )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c
index 12682c1190..e63a4626d4 100644
--- a/cpukit/libcsupport/src/libio.c
+++ b/cpukit/libcsupport/src/libio.c
@@ -1,524 +1,295 @@
/*
- * Provide UNIX/POSIX-like io system calls for RTEMS using the
- * RTEMS IO manager
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the low level
+ * POSIX system calls like open(), read, fstat(), etc.
+ *
+ * This provides the foundation for POSIX compliant IO system calls
+ * for RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
-#include <rtems.h>
-#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
-
-#include <stdio.h> /* O_RDONLY, et.al. */
-#include <fcntl.h> /* O_RDONLY, et.al. */
-#include <assert.h>
-
-#if ! defined(O_NDELAY)
-# if defined(solaris2)
-# define O_NDELAY O_NONBLOCK
-# elif defined(RTEMS_NEWLIB)
-# define O_NDELAY _FNBIO
-# endif
-#endif
-
-
-#include <errno.h>
-#include <string.h> /* strcmp */
-#include <unistd.h>
-#include <stdlib.h> /* calloc() */
-
-#include "libio.h" /* libio.h not pulled in by rtems */
+#include "libio_.h" /* libio_.h pulls in rtems */
/*
- * Semaphore to protect the io table
+ * Global variables used to manage the File Descriptor Table.
+ * IOP = IO Pointer.
*/
-Objects_Id rtems_libio_semaphore;
-
-#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
-#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
-
-extern unsigned32 rtems_libio_number_iops;
-rtems_libio_t *rtems_libio_iops;
-rtems_libio_t *rtems_libio_last_iop;
-
-#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
- &rtems_libio_iops[fd] : 0)
-
-#define rtems_libio_check_fd(fd) \
- do { \
- if ((unsigned32) (fd) >= rtems_libio_number_iops) \
- { \
- errno = EBADF; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_buffer(buffer) \
- do { \
- if ((buffer) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
-
-#define rtems_libio_check_count(count) \
- do { \
- if ((count) == 0) \
- { \
- return 0; \
- } \
- } while (0)
-
-#define rtems_libio_check_permissions(iop, flag) \
- do { \
- if (((iop)->flags & (flag)) == 0) \
- { \
- errno = EINVAL; \
- return -1; \
- } \
- } while (0)
+rtems_id rtems_libio_semaphore;
+rtems_libio_t *rtems_libio_iops;
+rtems_libio_t *rtems_libio_last_iop;
+rtems_libio_handler_t rtems_libio_handlers[15];
/*
- * External I/O handlers
- *
- * Space for all possible handlers is preallocated
- * to speed up dispatch to external handlers.
+ * rtems_register_libio_handler
+ *
+ * This function registers an external IO handler set. This lets
+ * other subsystems have their own versions of many of the system
+ * calls. For example, the networking code registers handlers which
+ * map the system calls for read() and write() to socket calls.
+ *
*/
-static rtems_libio_handler_t handlers[15];
-
-void
-rtems_register_libio_handler(
- int handler_flag,
- const rtems_libio_handler_t *handler
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
)
{
- int handler_index = rtems_file_descriptor_type_index(handler_flag);
+ int handler_index = rtems_file_descriptor_type_index( handler_flag );
+
if ((handler_index < 0) || (handler_index >= 15))
rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
- handlers[handler_index] = *handler;
-}
-
-/*
- * Called by bsp startup code to init the libio area.
- */
-void
-rtems_libio_init(void)
-{
- rtems_status_code rc;
-
- if (rtems_libio_number_iops > 0)
- {
- rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
- sizeof(rtems_libio_t));
- if (rtems_libio_iops == NULL)
- rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
-
- rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
- }
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_SEM,
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &rtems_libio_semaphore
- );
- if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_libio_handlers[handler_index] = *handler;
}
/*
- * Convert RTEMS status to a UNIX errno
+ * rtems_libio_init
+ *
+ * Called by BSP startup code to initialize the libio subsystem.
*/
-rtems_assoc_t errno_assoc[] = {
- { "OK", RTEMS_SUCCESSFUL, 0 },
- { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY },
- { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL },
- { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS },
- { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT },
- { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM },
- { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV },
- { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF},
- { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM},
- { "IO ERROR", RTEMS_IO_ERROR, EIO},
- { 0, 0, 0 },
-};
-
-static unsigned32
-rtems_libio_errno(rtems_status_code code)
+void rtems_libio_init( void )
{
- int rc;
-
- if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
- {
- errno = rc;
- return -1;
- }
- return -1;
+ rtems_status_code rc;
+
+ /*
+ * Allocate memory for the IOP Table
+ */
+
+ if ( rtems_libio_number_iops > 0 ) {
+ rtems_libio_iops =
+ (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t));
+
+ if (rtems_libio_iops == NULL)
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+
+ rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
+ }
+
+ /*
+ * Create the binary semaphore used to provide mutual exclusion
+ * on the IOP Table.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_SEM,
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_libio_semaphore
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ rtems_fatal_error_occurred( rc );
+
+ /*
+ * Initialize the base file system infrastructure.
+ */
+
+ rtems_filesystem_initialize();
}
/*
- * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
+ * rtems_libio_fcntl_flags
+ *
+ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
rtems_assoc_t access_modes_assoc[] = {
- { "READ", LIBIO_FLAGS_READ, O_RDONLY },
- { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
- { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
- { 0, 0, 0 },
+ { "READ", LIBIO_FLAGS_READ, O_RDONLY },
+ { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
+ { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
+ { 0, 0, 0 },
};
rtems_assoc_t status_flags_assoc[] = {
- { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
- { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
- { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
- { 0, 0, 0 },
+ { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
+ { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
+ { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
+ { 0, 0, 0 },
};
-static unsigned32
-rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+)
{
- unsigned32 flags = 0;
- unsigned32 access_modes;
+ unsigned32 flags = 0;
+ unsigned32 access_modes;
- /*
- * Access mode is a small integer
- */
-
- access_modes = fcntl_flags & O_ACCMODE;
- fcntl_flags &= ~O_ACCMODE;
- flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
+ /*
+ * Access mode is a small integer
+ */
+
+ access_modes = fcntl_flags & O_ACCMODE;
+ fcntl_flags &= ~O_ACCMODE;
+ flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
- /*
- * Everything else is single bits
- */
+ /*
+ * Everything else is single bits
+ */
- flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
- return flags;
+ flags |=
+ rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ return flags;
}
+/*
+ * rtems_libio_allocate
+ *
+ * This routine searches the IOP Table for an unused entry. If it
+ * finds one, it returns it. Otherwise, it returns NULL.
+ */
-static rtems_libio_t *
-rtems_libio_allocate(void)
+rtems_libio_t *rtems_libio_allocate( void )
{
- rtems_libio_t *iop;
- rtems_status_code rc;
-
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
- if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
- {
- /*
- * Got one; create a semaphore for it
- */
-
- rc = rtems_semaphore_create(
- RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
- 1,
- RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
- RTEMS_NO_PRIORITY,
- &iop->sem
- );
- if (rc != RTEMS_SUCCESSFUL)
- goto failed;
-
- iop->flags = LIBIO_FLAGS_OPEN;
- goto done;
- }
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
+ if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
+ /*
+ * Got an IOP -- create a semaphore for it.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &iop->sem
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ goto failed;
+ iop->flags = LIBIO_FLAGS_OPEN;
+ goto done;
+ }
+
failed:
- iop = 0;
-
+ iop = 0;
+
done:
- rtems_semaphore_release(rtems_libio_semaphore);
- return iop;
+ rtems_semaphore_release( rtems_libio_semaphore );
+ return iop;
}
-static void
-rtems_libio_free(rtems_libio_t *iop)
-{
- rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- if (iop->sem)
- rtems_semaphore_delete(iop->sem);
- (void) memset(iop, 0, sizeof(*iop));
-
- rtems_semaphore_release(rtems_libio_semaphore);
-}
+/*
+ * rtems_libio_free
+ *
+ * This routine frees the resources associated with an IOP (file descriptor)
+ * and clears the slot in the IOP Table.
+ */
-int
-__rtems_open(
- const char *pathname,
- unsigned32 flag,
- unsigned32 mode)
+void rtems_libio_free(
+ rtems_libio_t *iop
+)
{
- rtems_status_code rc;
- rtems_libio_t *iop = 0;
- rtems_driver_name_t *np;
- rtems_libio_open_close_args_t args;
-
- /*
- * Additional external I/O handlers would be supported by
- * adding code to pick apart the pathname appropriately.
- * The networking code does not require changes here since
- * network file descriptors are obtained using socket(), not
- * open().
- */
-
- if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
- goto done;
-
- iop = rtems_libio_allocate();
- if (iop == 0)
- {
- rc = RTEMS_TOO_MANY;
- goto done;
- }
-
- iop->driver = np;
- iop->pathname = (char *) pathname;
- iop->flags |= rtems_libio_fcntl_flags(flag);
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.flags = iop->flags;
- args.mode = mode;
+ if (iop->sem)
+ rtems_semaphore_delete(iop->sem);
- rc = rtems_io_open(np->major, np->minor, (void *) &args);
-
-done:
-
- if (rc != RTEMS_SUCCESSFUL)
- {
- if (iop)
- rtems_libio_free(iop);
- return rtems_libio_errno(rc);
- }
-
- return iop - rtems_libio_iops;
-}
-
-int
-__rtems_close(
- int fd
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_open_close_args_t args;
- int status;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].close;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- status = (*fp)(fd);
- return status;
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+ (void) memset(iop, 0, sizeof(*iop));
- np = iop->driver;
-
- args.iop = iop;
- args.flags = 0;
- args.mode = 0;
-
- rc = rtems_io_close(np->major, np->minor, (void *) &args);
+ rtems_semaphore_release( rtems_libio_semaphore );
+}
- rtems_libio_free(iop);
+/*
+ * rtems_libio_is_open_files_in_fs
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * are any active file descriptors that refer to the atleast one node in the
+ * file system that we are trying to dismount.
+ *
+ * If there is at least one node in the file system referenced by the mount
+ * table entry a 1 is returned, otherwise a 0 is returned.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
- return 0;
-}
-
-int
-__rtems_read(
- int fd,
- void * buffer,
- unsigned32 count
- )
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t * fs_mt_entry
+)
{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].read;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+ rtems_libio_t *iop;
+ int result = 0;
- np = iop->driver;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
+ /*
+ * Look for any active file descriptor entry.
+ */
- rc = rtems_io_read(np->major, np->minor, (void *) &args);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- iop->offset += args.bytes_moved;
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
- return args.bytes_moved;
-}
-
-int
-__rtems_write(
- int fd,
- const void *buffer,
- unsigned32 count
- )
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_rw_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, const void *buffer, unsigned32 count);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].write;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, buffer, count);
+ if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
+ result = 1;
+ break;
+ }
}
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
- rtems_libio_check_buffer(buffer);
- rtems_libio_check_count(count);
- rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
-
- np = iop->driver;
-
- args.iop = iop;
- args.offset = iop->offset;
- args.buffer = (void *) buffer;
- args.count = count;
- args.flags = iop->flags;
- args.bytes_moved = 0;
-
- rc = rtems_io_write(np->major, np->minor, (void *) &args);
+ }
- iop->offset += args.bytes_moved;
+ rtems_semaphore_release( rtems_libio_semaphore );
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
-
- return args.bytes_moved;
+ return result;
}
-int
-__rtems_ioctl(
- int fd,
- unsigned32 command,
- void * buffer)
-{
- rtems_status_code rc;
- rtems_driver_name_t *np;
- rtems_libio_t *iop;
- rtems_libio_ioctl_args_t args;
-
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, unsigned32 command, void *buffer);
-
- fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, command, buffer);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
+/*
+ * rtems_libio_is_file_open
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * given file refers to an active file descriptor.
+ *
+ * If the given file is open a 1 is returned, otherwise a 0 is returned.
+ */
- np = iop->driver;
+int rtems_libio_is_file_open(
+ void *node_access
+)
+{
+ rtems_libio_t *iop;
+ int result=0;
- args.iop = iop;
- args.command = command;
- args.buffer = buffer;
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
- rc = rtems_io_control(np->major, np->minor, (void *) &args);
+ /*
+ * Look for any active file descriptor entry.
+ */
- if (rc != RTEMS_SUCCESSFUL)
- return rtems_libio_errno(rc);
+ for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
- return args.ioctl_return;
-}
-
-/*
- * internal only??
- */
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
-int
-__rtems_lseek(
- int fd,
- rtems_libio_offset_t offset,
- int whence
- )
-{
- rtems_libio_t *iop;
+ if ( iop->pathinfo.node_access == node_access ) {
+ result = 1;
+ break;
+ }
+ }
+ }
- if (rtems_file_descriptor_type(fd)) {
- int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_semaphore_release( rtems_libio_semaphore );
- fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
- if (fp == NULL) {
- errno = EBADF;
- return -1;
- }
- return (*fp)(fd, offset, whence);
- }
- iop = rtems_libio_iop(fd);
- rtems_libio_check_fd(fd);
-
- switch (whence)
- {
- case SEEK_SET:
- iop->offset = offset;
- break;
-
- case SEEK_CUR:
- iop->offset += offset;
- break;
-
- case SEEK_END:
- iop->offset = iop->size - offset;
- break;
-
- default:
- errno = EINVAL;
- return -1;
- }
- return 0;
+ return result;
}
diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c
new file mode 100644
index 0000000000..1cee54d0bf
--- /dev/null
+++ b/cpukit/libcsupport/src/link.c
@@ -0,0 +1,60 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+ result = (*parent_loc.ops->evalformake)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 )
+ set_errno_and_return_minus_one( result );
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry )
+ set_errno_and_return_minus_one( EXDEV );
+
+ if ( !parent_loc.ops->link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start );
+}
diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c
new file mode 100644
index 0000000000..514f8cd912
--- /dev/null
+++ b/cpukit/libcsupport/src/lseek.c
@@ -0,0 +1,93 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+
+#include "libio_.h"
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_lseek_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, offset, whence );
+ }
+
+ /*
+ * Now process the lseek().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ switch ( whence ) {
+ case SEEK_SET:
+ iop->offset = offset;
+ break;
+
+ case SEEK_CUR:
+ iop->offset += offset;
+ break;
+
+ case SEEK_END:
+ iop->offset = iop->size - offset;
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ( !iop->handlers->lseek )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->lseek)( iop, offset, whence );
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
+
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
index fac38585a7..f164e45f6c 100644
--- a/cpukit/libcsupport/src/malloc.c
+++ b/cpukit/libcsupport/src/malloc.c
@@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize(
#ifdef MALLOC_STATS
/* zero all the stats */
- (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats));
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
#endif
MSBUMP(space_available, length);
@@ -220,9 +220,11 @@ void *malloc(
{
unsigned32 actual_size;
unsigned32 current_depth;
- status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size);
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
MSBUMP(lifetime_allocated, actual_size);
- current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
if (current_depth > rtems_malloc_stats.max_depth)
rtems_malloc_stats.max_depth = current_depth;
}
@@ -335,10 +337,12 @@ void free(
void malloc_dump(void)
{
- unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
printf("Malloc stats\n");
- printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
(unsigned int) rtems_malloc_stats.space_available / 1024,
(unsigned int) allocated / 1024,
/* avoid float! */
diff --git a/cpukit/libcsupport/src/mkdir.c b/cpukit/libcsupport/src/mkdir.c
new file mode 100644
index 0000000000..18fc7171c7
--- /dev/null
+++ b/cpukit/libcsupport/src/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
+
diff --git a/cpukit/libcsupport/src/mkfifo.c b/cpukit/libcsupport/src/mkfifo.c
new file mode 100644
index 0000000000..6b3ece5650
--- /dev/null
+++ b/cpukit/libcsupport/src/mkfifo.c
@@ -0,0 +1,25 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c
new file mode 100644
index 0000000000..4f83321ecd
--- /dev/null
+++ b/cpukit/libcsupport/src/mknod.c
@@ -0,0 +1,60 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc );
+}
diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c
new file mode 100644
index 0000000000..fa8cebc3f9
--- /dev/null
+++ b/cpukit/libcsupport/src/mount.c
@@ -0,0 +1,299 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+/*
+ * XXX
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+);
+
+int init_fs_mount_table( void );
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_options_t options;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Are the file system options valid?
+ */
+
+ options = get_file_system_options( fsoptions );
+ if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Is the file system type valid?
+ */
+
+ if ( fs_ops == NULL ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) );
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if( device )
+ sprintf( temp_mt_entry->dev, "%s", device );
+ else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+ if ( rtems_filesystem_evaluate_path(
+ mount_point,
+ RTEMS_LIBIO_PERMS_RWX,
+ &temp_loc ,
+ TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry
+ */
+
+ temp_mt_entry->mt_point_node.node_access = temp_loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = temp_loc.handlers;
+ temp_mt_entry->mt_point_node.ops = temp_loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !temp_loc.ops->mount ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( temp_loc.ops->mount( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ }
+ else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( !fs_ops->fsmount_me ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( fs_ops->fsmount_me( temp_mt_entry ) )
+ goto cleanup_and_bail;
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * get_file_system_options
+ *
+ * This routine will determine is the text string that represents the options
+ * that are to be used to mount the file system are actually valid. If the
+ * options are valid the appropriate file system options type will be returned
+ * to the calling routine.
+ */
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+)
+{
+ if ( strcmp( "RO", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_ONLY;
+ if ( strcmp( "RW", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_WRITE_ONLY;
+ else
+ return RTEMS_FILESYSTEM_BAD_OPTIONS;
+}
+
+
+
+/*
+ * search_mt_for_mount_point
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_point_node to the node describing the selected
+ * mount point.. If any of the mount table file system mount point nodes
+ * match the new file system selected mount point node, we are attempting
+ * to mount the new file system onto a node that already has a file system
+ * mounted to it. This is not a permitted operation.
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_point_node.node_access ==
+ location_of_mount_point->node_access )
+ return FOUND;
+ }
+ return NOT_FOUND;
+}
+
diff --git a/cpukit/libcsupport/src/newlibc.c b/cpukit/libcsupport/src/newlibc.c
index a6acc1c8d7..bea592a46e 100644
--- a/cpukit/libcsupport/src/newlibc.c
+++ b/cpukit/libcsupport/src/newlibc.c
@@ -1,21 +1,14 @@
-
/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
* COPYRIGHT (c) 1994 by Division Incorporated
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
- * Description:
- * Implementation of hooks for the CYGNUS newlib libc
- * These hooks set things up so that:
- * '_REENT' is switched at task switch time.
- *
- *
- * TODO:
- *
- * NOTE:
- *
* $Id$
*
*/
@@ -47,7 +40,21 @@
#include <stdio.h>
#endif
-#include "internal.h"
+/*
+ * Private routines
+ */
+
+void MY_task_set_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad,
+ rtems_unsigned32 note
+);
+
+rtems_unsigned32 MY_task_get_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad
+);
+
#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
@@ -304,7 +311,7 @@ libc_init(int reentrant)
rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
&libc_extension, &extension_id);
if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_fatal_error_occurred( rc );
libc_reentrant = reentrant;
}
@@ -353,11 +360,14 @@ int get_errno()
/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
#if !defined(RTEMS_UNIX) && !defined(_AM29K)
+#if !defined(pc386)
void _exit(int status)
{
libc_wrapup(); /* Why? XXX */
rtems_shutdown_executive(status);
}
+#endif
+
#else
void exit(int status)
@@ -426,4 +436,46 @@ unsigned int sleep(
#endif
+/*
+ * Newlib Interface Support
+ *
+ * Routines to Access Internal RTEMS Resources without violating
+ * kernel visibility.
+ *
+ */
+
+void MY_task_set_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad,
+ unsigned32 note
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( api )
+ api->Notepads[ notepad ] = note;
+}
+
+
+unsigned32 MY_task_get_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ return api->Notepads[ notepad ];
+}
+
+void *MY_CPU_Context_FP_start(
+ void *base,
+ unsigned32 offset
+)
+{
+ return _CPU_Context_Fp_start( base, offset );
+}
#endif
diff --git a/cpukit/libcsupport/src/no_libc.c b/cpukit/libcsupport/src/no_libc.c
index 5a58ba761c..4bd02c4b27 100644
--- a/cpukit/libcsupport/src/no_libc.c
+++ b/cpukit/libcsupport/src/no_libc.c
@@ -1,6 +1,4 @@
-
-/* no_libc.h
- *
+/*
* This file contains stubs for the reentrancy hooks when
* an unknown C library is used.
*
@@ -17,15 +15,15 @@
#include <rtems.h>
-#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
#include "libcsupport.h"
-#include "internal.h"
#include <stdlib.h> /* for free() */
-void
-libc_init(int reentrant)
+void libc_init(
+ int reentrant
+)
{
}
@@ -34,11 +32,15 @@ void libc_suspend_main(void)
}
-void libc_global_exit(rtems_unsigned32 code)
+void libc_global_exit(
+ rtems_unsigned32 code
+)
{
}
-void _exit(int status)
+void _exit(
+ int status
+)
{
}
diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c
new file mode 100644
index 0000000000..4cdf5acf35
--- /dev/null
+++ b/cpukit/libcsupport/src/open.c
@@ -0,0 +1,202 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and eitehr the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * Additional external I/O handlers would be supported by adding
+ * code to pick apart the pathname appropriately. The networking
+ * code does not require changes here since network file
+ * descriptors are obtained using socket(), not open().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+
+ status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ goto done;
+ }
+
+ /*
+ * Fill in the file control block based on the temp_loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = temp_loc.handlers;
+ iop->file_info = temp_loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = temp_loc;
+
+ if ( !iop->handlers->open ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ set_errno_and_return_minus_one( rc );
+ }
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/cpukit/libcsupport/src/opendir.c b/cpukit/libcsupport/src/opendir.c
index e303eb28e5..f0e9488684 100644
--- a/cpukit/libcsupport/src/opendir.c
+++ b/cpukit/libcsupport/src/opendir.c
@@ -1,17 +1,85 @@
/*
* opendir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
-DIR *opendir(
- const char *name
-)
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
{
- return NULL;
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
}
diff --git a/cpukit/libcsupport/src/pathconf.c b/cpukit/libcsupport/src/pathconf.c
new file mode 100644
index 0000000000..e19d1329f4
--- /dev/null
+++ b/cpukit/libcsupport/src/pathconf.c
@@ -0,0 +1,38 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/cpukit/libcsupport/src/pipe.c b/cpukit/libcsupport/src/pipe.c
new file mode 100644
index 0000000000..35dcf627bb
--- /dev/null
+++ b/cpukit/libcsupport/src/pipe.c
@@ -0,0 +1,23 @@
+/*
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+int pipe(
+ int filsdes[2]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/libcsupport/src/read.c b/cpukit/libcsupport/src/read.c
new file mode 100644
index 0000000000..150fe675ab
--- /dev/null
+++ b/cpukit/libcsupport/src/read.c
@@ -0,0 +1,84 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int read(
+ int fd,
+ void *buffer,
+ unsigned32 count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_read_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the read().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libcsupport/src/readdir.c b/cpukit/libcsupport/src/readdir.c
index d592a62b99..f950d56171 100644
--- a/cpukit/libcsupport/src/readdir.c
+++ b/cpukit/libcsupport/src/readdir.c
@@ -1,14 +1,77 @@
/*
* readdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
-struct dirent *readdir(
- register DIR *dirp
-)
-{
- return NULL;
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
}
diff --git a/cpukit/libcsupport/src/readlink.c b/cpukit/libcsupport/src/readlink.c
new file mode 100644
index 0000000000..22de51e88f
--- /dev/null
+++ b/cpukit/libcsupport/src/readlink.c
@@ -0,0 +1,43 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if (!buf)
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( !loc.ops->readlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->readlink)( &loc, buf, bufsize );
+}
diff --git a/cpukit/libcsupport/src/rewinddir.c b/cpukit/libcsupport/src/rewinddir.c
index c85e6fd4d0..04313a6042 100644
--- a/cpukit/libcsupport/src/rewinddir.c
+++ b/cpukit/libcsupport/src/rewinddir.c
@@ -1,7 +1,14 @@
/*
* rewinddir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/types.h>
@@ -15,6 +22,14 @@ void rewinddir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
+
}
diff --git a/cpukit/libcsupport/src/rmdir.c b/cpukit/libcsupport/src/rmdir.c
new file mode 100644
index 0000000000..6c0331087f
--- /dev/null
+++ b/cpukit/libcsupport/src/rmdir.c
@@ -0,0 +1,56 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libio_.h"
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.ops->rmnod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->rmnod)( &loc );
+}
diff --git a/cpukit/libcsupport/src/scandir.c b/cpukit/libcsupport/src/scandir.c
index 380415dd97..9ba1cb7bec 100644
--- a/cpukit/libcsupport/src/scandir.c
+++ b/cpukit/libcsupport/src/scandir.c
@@ -1,7 +1,50 @@
/*
* scandir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
@@ -9,15 +52,98 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-int scandir(
- const char *dirname,
- struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*dcomp)(const void *, const void *)
-)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d, *p, **names;
+ register size_t nitems;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1);
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1); /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
{
- errno = ENOSYS;
- return -1;
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
}
diff --git a/cpukit/libcsupport/src/seekdir.c b/cpukit/libcsupport/src/seekdir.c
index e591adbb9f..80802b56c6 100644
--- a/cpukit/libcsupport/src/seekdir.c
+++ b/cpukit/libcsupport/src/seekdir.c
@@ -1,7 +1,14 @@
/*
* seekdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -12,10 +19,20 @@
#include <errno.h>
void seekdir(
- DIR *dirp,
- long loc
+ DIR *dirp,
+ long loc
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
}
diff --git a/cpukit/libcsupport/src/stat.c b/cpukit/libcsupport/src/stat.c
new file mode 100644
index 0000000000..8ad7e61511
--- /dev/null
+++ b/cpukit/libcsupport/src/stat.c
@@ -0,0 +1,79 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int stat(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ return (*loc.handlers->fstat)( &loc, buf );
+}
+#endif
+
+/*
+ * _stat_r
+ *
+ * This is the Newlib dependent reentrant version of stat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _stat_r(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return stat( path, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/symlink.c b/cpukit/libcsupport/src/symlink.c
new file mode 100644
index 0000000000..ca9673f51b
--- /dev/null
+++ b/cpukit/libcsupport/src/symlink.c
@@ -0,0 +1,34 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ return (*loc.ops->symlink)( &loc, actualpath, name_start);
+}
+
diff --git a/cpukit/libcsupport/src/tcdrain.c b/cpukit/libcsupport/src/tcdrain.c
index 585871cc90..c2749a90e1 100644
--- a/cpukit/libcsupport/src/tcdrain.c
+++ b/cpukit/libcsupport/src/tcdrain.c
@@ -1,9 +1,15 @@
/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcdrain.
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
*
+ * $Id$
*/
#include <rtems.h>
@@ -13,14 +19,15 @@
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>
+#include <sys/ioctl.h>
-#include "internal.h"
#include "libio.h"
-int
-tcdrain(int fd)
+int tcdrain(
+ int fd
+)
{
- return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0);
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
}
#endif
diff --git a/cpukit/libcsupport/src/tcgetattr.c b/cpukit/libcsupport/src/tcgetattr.c
new file mode 100644
index 0000000000..2d3e4d7e3c
--- /dev/null
+++ b/cpukit/libcsupport/src/tcgetattr.c
@@ -0,0 +1,33 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/cpukit/libcsupport/src/tcsetattr.c b/cpukit/libcsupport/src/tcsetattr.c
new file mode 100644
index 0000000000..c0ed509a0f
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsetattr.c
@@ -0,0 +1,38 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+#include "libio_.h"
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ if ( opt != TCSANOW )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/cpukit/libcsupport/src/telldir.c b/cpukit/libcsupport/src/telldir.c
index eee8d925ec..cea6cc08cb 100644
--- a/cpukit/libcsupport/src/telldir.c
+++ b/cpukit/libcsupport/src/telldir.c
@@ -1,7 +1,14 @@
/*
* telldir() - XXX
*
- * $Id$
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <sys/param.h>
@@ -9,15 +16,24 @@
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
-#include <rtems.h>
-#include "libio.h"
+#include "libio_.h"
+
long telldir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ rtems_libio_t *iop;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
}
diff --git a/cpukit/libcsupport/src/truncate.c b/cpukit/libcsupport/src/truncate.c
new file mode 100644
index 0000000000..145e596654
--- /dev/null
+++ b/cpukit/libcsupport/src/truncate.c
@@ -0,0 +1,41 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
+
diff --git a/cpukit/libcsupport/src/umask.c b/cpukit/libcsupport/src/umask.c
new file mode 100644
index 0000000000..35229a30a1
--- /dev/null
+++ b/cpukit/libcsupport/src/umask.c
@@ -0,0 +1,30 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libio_.h"
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/cpukit/libcsupport/src/unixlibc.c b/cpukit/libcsupport/src/unixlibc.c
index 3e757e313d..a581d95534 100644
--- a/cpukit/libcsupport/src/unixlibc.c
+++ b/cpukit/libcsupport/src/unixlibc.c
@@ -1,5 +1,15 @@
/*
* $Id$
+ * UNIX Port C Library Support
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
*/
#include <rtems.h>
diff --git a/cpukit/libcsupport/src/unlink.c b/cpukit/libcsupport/src/unlink.c
new file mode 100644
index 0000000000..d4a5520bcb
--- /dev/null
+++ b/cpukit/libcsupport/src/unlink.c
@@ -0,0 +1,44 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ if ( !loc.ops->unlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->unlink)( &loc );
+}
diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c
new file mode 100644
index 0000000000..f50e63ff42
--- /dev/null
+++ b/cpukit/libcsupport/src/unmount.c
@@ -0,0 +1,214 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+);
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a mount_path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *mount_path
+)
+{
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_mount_table_entry_t temp_mt_entry;
+ int result;
+
+ /*
+ * Are there any file systems below the mount_path specified
+ */
+
+ status = file_systems_below_this_mountpoint(
+ mount_path,
+ &temp_loc,
+ &temp_mt_entry
+ );
+
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Is the current node reference pointing to a node in the file system
+ * we are attempting to unmount ?
+ */
+
+ if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being mounted on to do its cleanup.
+ * XXX - Did I change these correctly ??? It looks like either I did
+ * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped.
+ * XXX Add to the mt_point_node unmount to set the mt_entry back to null
+ * XXX I will step off in space when evaluating past the end of the node.
+ */
+
+ if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Run the unmount function for the subordinate file system.
+ */
+
+ if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the file system to clean up.
+ */
+
+ result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry );
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry );
+
+ /*
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ free( temp_loc.mt_entry );
+
+ return result;
+
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+ rtems_filesystem_mount_table_entry_t *current_fs_mt_entry;
+
+ /*
+ * Is the mount_path even a valid node name in the existing tree?
+ */
+
+ if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) )
+ return -1;
+
+ /*
+ * Look for the node defined in temp_loc as a mount point in the
+ * mount table chain.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.node_access ==
+ temp_loc->node_access ) {
+ current_fs_mt_entry = the_mount_entry;
+ *temp_loc = current_fs_mt_entry->mt_fs_root;
+ goto after_real_mount_point_found;
+ }
+ }
+ set_errno_and_return_minus_one( EACCES );
+
+
+after_real_mount_point_found:
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+
+ /*
+ * Exclude the current file systems mount table entry from the test
+ */
+
+ if ( current_fs_mt_entry != the_mount_entry ) {
+ if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) {
+
+ /*
+ * There is at least one fs below the fs on the mount_path.
+ */
+ set_errno_and_return_minus_one( EBUSY );
+ }
+ }
+ }
+
+ *temp_mt_entry = *current_fs_mt_entry;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/utime.c b/cpukit/libcsupport/src/utime.c
new file mode 100644
index 0000000000..f1a12ee1b2
--- /dev/null
+++ b/cpukit/libcsupport/src/utime.c
@@ -0,0 +1,35 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime );
+}
diff --git a/cpukit/libcsupport/src/write.c b/cpukit/libcsupport/src/write.c
new file mode 100644
index 0000000000..7e0953bb90
--- /dev/null
+++ b/cpukit/libcsupport/src/write.c
@@ -0,0 +1,92 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "libio_.h"
+
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int write( /* XXX this should return a ssize_t */
+ int fd,
+ const void *buffer,
+ unsigned32 count /* XXX this should be a size_t */
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_write_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the write() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->write )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+long _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libfs/src/imfs/imfs_chown.c b/cpukit/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_fchmod.c b/cpukit/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/cpukit/libfs/src/imfs/imfs_free.c b/cpukit/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_getchild.c b/cpukit/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_gtkn.c b/cpukit/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/cpukit/libfs/src/imfs/imfs_mount.c b/cpukit/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_ntype.c b/cpukit/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_readlink.c b/cpukit/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_symlink.c b/cpukit/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/cpukit/libfs/src/imfs/imfs_unlink.c b/cpukit/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_unmount.c b/cpukit/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_utime.c b/cpukit/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/ioman.c b/cpukit/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/cpukit/libfs/src/imfs/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/cpukit/posix/src/getpid.c b/cpukit/posix/src/getpid.c
index b42981398a..8e912adf39 100644
--- a/cpukit/posix/src/getpid.c
+++ b/cpukit/posix/src/getpid.c
@@ -20,3 +20,22 @@ pid_t getpid( void )
{
return _Objects_Local_node;
}
+
+/*
+ * _getpid_r
+ *
+ * This is the Newlib dependent reentrant version of getpid().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+pid_t _getpid_r(
+ struct _reent *ptr
+)
+{
+ return getpid();
+}
+#endif
+
diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c
index 5db634a924..1450164021 100644
--- a/cpukit/posix/src/psignal.c
+++ b/cpukit/posix/src/psignal.c
@@ -1222,6 +1222,26 @@ int kill(
}
/*
+ * _kill_r
+ *
+ * This is the Newlib dependent reentrant version of kill().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _kill_r(
+ struct _reent *ptr,
+ pid_t pid,
+ int sig
+)
+{
+ return kill( pid, sig );
+}
+#endif
+
+/*
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
*/
diff --git a/cpukit/sapi/src/io.c b/cpukit/sapi/src/io.c
index 92de490885..d6e669c4fc 100644
--- a/cpukit/sapi/src/io.c
+++ b/cpukit/sapi/src/io.c
@@ -92,6 +92,7 @@ void _IO_Initialize_all_drivers( void )
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_register_name(
char *device_name,
rtems_device_major_number major,
@@ -124,6 +125,7 @@ rtems_status_code rtems_io_register_name(
return RTEMS_TOO_MANY;
}
+#endif
/*PAGE
*
@@ -140,6 +142,7 @@ rtems_status_code rtems_io_register_name(
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_lookup_name(
const char *name,
rtems_driver_name_t **device_info
@@ -161,6 +164,7 @@ rtems_status_code rtems_io_lookup_name(
*device_info = 0;
return RTEMS_UNSATISFIED;
}
+#endif
/*PAGE
diff --git a/testsuites/sptests/spsize/size.c b/testsuites/sptests/spsize/size.c
index 97281c9ee3..d12ff93305 100644
--- a/testsuites/sptests/spsize/size.c
+++ b/testsuites/sptests/spsize/size.c
@@ -30,8 +30,10 @@
#include <rtems/rtems/intr.h>
#include <rtems/io.h>
#include <rtems/rtems/message.h>
+#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/rtems/mp.h>
#include <rtems/score/mpci.h>
+#endif
#include <rtems/rtems/part.h>
#include <rtems/score/priority.h>
#include <rtems/rtems/ratemon.h>
@@ -105,12 +107,22 @@
#define MPCI_RECEIVE_SERVER_STACK_SIZE 0
#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#define MP_SYSTEM_TASKS \
+ (MPCI_RECEIVE_SERVER_STACK_SIZE + \
+ sizeof(Thread_Control) + \
+ MPCI_RECEIVE_SERVER_FP)
+#else
+#define MP_SYSTEM_TASKS 0
+#endif
+
+/*
+ * Idle and the MPCI Receive Server Threads
+ */
+
#define SYSTEM_TASKS \
- (STACK_MINIMUM_SIZE + \
- MPCI_RECEIVE_SERVER_STACK_SIZE + \
- (2*sizeof(Thread_Control))) + \
- MPCI_RECEIVE_SERVER_FP + \
- SYSTEM_IDLE_FP
+ (STACK_MINIMUM_SIZE + sizeof(Thread_Control) + SYSTEM_IDLE_FP + \
+ MP_SYSTEM_TASKS)
#define rtems_unsigned32 unsigned32