Whamcloud - gitweb
import older libsysio snapshot.
authorjacob <jacob>
Sun, 19 Dec 2004 22:54:41 +0000 (22:54 +0000)
committerjacob <jacob>
Sun, 19 Dec 2004 22:54:41 +0000 (22:54 +0000)
112 files changed:
libsysio/AUTHORS [new file with mode: 0644]
libsysio/COPYING [new file with mode: 0644]
libsysio/ChangeLog [new file with mode: 0644]
libsysio/Makefile.am [new file with mode: 0644]
libsysio/NEWS [new file with mode: 0644]
libsysio/README [new file with mode: 0644]
libsysio/Rules.make [new file with mode: 0644]
libsysio/autogen.sh [new file with mode: 0755]
libsysio/configure.in [new file with mode: 0644]
libsysio/dev/stdfd/module.mk [new file with mode: 0644]
libsysio/dev/stdfd/stdfd.c [new file with mode: 0644]
libsysio/dev/stdfd/stdfd.h [new file with mode: 0644]
libsysio/drivers/incore/README [new file with mode: 0644]
libsysio/drivers/incore/fs_incore.c [new file with mode: 0644]
libsysio/drivers/incore/fs_incore.h [new file with mode: 0644]
libsysio/drivers/incore/module.mk [new file with mode: 0644]
libsysio/drivers/native/fs_native.c [new file with mode: 0644]
libsysio/drivers/native/fs_native.h [new file with mode: 0644]
libsysio/drivers/native/module.mk [new file with mode: 0644]
libsysio/drivers/sockets/module.mk [new file with mode: 0644]
libsysio/drivers/sockets/sockets.c [new file with mode: 0644]
libsysio/drivers/yod/fs_yod.c [new file with mode: 0644]
libsysio/drivers/yod/fs_yod.h [new file with mode: 0644]
libsysio/drivers/yod/module.mk [new file with mode: 0644]
libsysio/include/cplant-yod.h [new file with mode: 0644]
libsysio/include/dev.h [new file with mode: 0644]
libsysio/include/file.h [new file with mode: 0644]
libsysio/include/fs.h [new file with mode: 0644]
libsysio/include/inode.h [new file with mode: 0644]
libsysio/include/module.mk [new file with mode: 0644]
libsysio/include/mount.h [new file with mode: 0644]
libsysio/include/namespace.h [new file with mode: 0644]
libsysio/include/sysio-symbols.h [new file with mode: 0644]
libsysio/include/sysio.h [new file with mode: 0644]
libsysio/include/xtio.h [new file with mode: 0644]
libsysio/misc/gdb-libsysio [new file with mode: 0644]
libsysio/misc/init-env.sh [new file with mode: 0644]
libsysio/src/access.c [new file with mode: 0644]
libsysio/src/chdir.c [new file with mode: 0644]
libsysio/src/chmod.c [new file with mode: 0644]
libsysio/src/chown.c [new file with mode: 0644]
libsysio/src/dev.c [new file with mode: 0644]
libsysio/src/dup.c [new file with mode: 0644]
libsysio/src/fcntl.c [new file with mode: 0644]
libsysio/src/file.c [new file with mode: 0644]
libsysio/src/file_hack.c [new file with mode: 0644]
libsysio/src/fs.c [new file with mode: 0644]
libsysio/src/fsync.c [new file with mode: 0644]
libsysio/src/getdirentries.c [new file with mode: 0644]
libsysio/src/init.c [new file with mode: 0644]
libsysio/src/inode.c [new file with mode: 0644]
libsysio/src/ioctl.c [new file with mode: 0644]
libsysio/src/ioctx.c [new file with mode: 0644]
libsysio/src/iowait.c [new file with mode: 0644]
libsysio/src/link.c [new file with mode: 0644]
libsysio/src/lseek.c [new file with mode: 0644]
libsysio/src/mkdir.c [new file with mode: 0644]
libsysio/src/mknod.c [new file with mode: 0644]
libsysio/src/module.mk [new file with mode: 0644]
libsysio/src/mount.c [new file with mode: 0644]
libsysio/src/namei.c [new file with mode: 0644]
libsysio/src/open.c [new file with mode: 0644]
libsysio/src/readlink.c [new file with mode: 0644]
libsysio/src/rename.c [new file with mode: 0644]
libsysio/src/rmdir.c [new file with mode: 0644]
libsysio/src/rw.c [new file with mode: 0644]
libsysio/src/stat.c [new file with mode: 0644]
libsysio/src/stat64.c [new file with mode: 0644]
libsysio/src/statvfs.c [new file with mode: 0644]
libsysio/src/statvfs64.c [new file with mode: 0644]
libsysio/src/stdlib.c [new file with mode: 0644]
libsysio/src/symlink.c [new file with mode: 0644]
libsysio/src/truncate.c [new file with mode: 0644]
libsysio/src/unlink.c [new file with mode: 0644]
libsysio/src/utime.c [new file with mode: 0644]
libsysio/tests/Makefile.am [new file with mode: 0644]
libsysio/tests/README [new file with mode: 0644]
libsysio/tests/cleanup.pl [new file with mode: 0755]
libsysio/tests/drv_init_all.c [new file with mode: 0644]
libsysio/tests/gendrvdata.sh [new file with mode: 0644]
libsysio/tests/help.c [new file with mode: 0644]
libsysio/tests/helper.pm [new file with mode: 0644]
libsysio/tests/module.mk [new file with mode: 0644]
libsysio/tests/populator.pl [new file with mode: 0755]
libsysio/tests/setup.pl [new file with mode: 0755]
libsysio/tests/startup.c [new file with mode: 0644]
libsysio/tests/sysio_stubs.c [new file with mode: 0644]
libsysio/tests/sysio_tests.c [new file with mode: 0644]
libsysio/tests/test.h [new file with mode: 0644]
libsysio/tests/test_all.pl [new file with mode: 0755]
libsysio/tests/test_copy.bash [new file with mode: 0644]
libsysio/tests/test_copy.c [new file with mode: 0644]
libsysio/tests/test_copy.pl [new file with mode: 0755]
libsysio/tests/test_driver.c [new file with mode: 0644]
libsysio/tests/test_driver.h [new file with mode: 0644]
libsysio/tests/test_getcwd.c [new file with mode: 0644]
libsysio/tests/test_getcwd.pl [new file with mode: 0755]
libsysio/tests/test_link.c [new file with mode: 0644]
libsysio/tests/test_list.c [new file with mode: 0644]
libsysio/tests/test_list.pl [new file with mode: 0755]
libsysio/tests/test_path.c [new file with mode: 0644]
libsysio/tests/test_path.pl [new file with mode: 0755]
libsysio/tests/test_regions.c [new file with mode: 0644]
libsysio/tests/test_rename.c [new file with mode: 0644]
libsysio/tests/test_rw.pl [new file with mode: 0755]
libsysio/tests/test_stats.c [new file with mode: 0644]
libsysio/tests/test_stats.pl [new file with mode: 0755]
libsysio/tests/test_stdfd.pl [new file with mode: 0755]
libsysio/tests/test_strided.pl [new file with mode: 0755]
libsysio/tests/test_symlink.pl [new file with mode: 0755]
libsysio/tests/test_unlink.c [new file with mode: 0644]
libsysio/tests/verifier.pl [new file with mode: 0755]

diff --git a/libsysio/AUTHORS b/libsysio/AUTHORS
new file mode 100644 (file)
index 0000000..7293307
--- /dev/null
@@ -0,0 +1 @@
+Lee Ward <lee@sandia.gov>
diff --git a/libsysio/COPYING b/libsysio/COPYING
new file mode 100644 (file)
index 0000000..2bb5b6e
--- /dev/null
@@ -0,0 +1,502 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/libsysio/ChangeLog b/libsysio/ChangeLog
new file mode 100644 (file)
index 0000000..126c27f
--- /dev/null
@@ -0,0 +1,31 @@
+Sat Feb 22 10:32:10 EST 2003
+       Created <lee@sandia.gov>
+---
+
+*Added mount() api call to support sub-mounts.
+
+*Added rudimentary automounts per the namespace chapter in the "Lustre
+Architecture Reference". Note, full URI support is not implemented. See
+the README for details.
+
+Think I have it going for simultaneous 32/64 bit support. Together with
+the nagging build for test_stat.
+
+*Miscellaneous bugs fixed.
+
+---
+Lee -- Sat Mar 22 15:01:45 EST 2003
+
+*Added "incore" file system. An in-memory file system solving boot-strap
+and other annoying little chicken-and-the-egg problems.
+
+*Added support for devices
+
+*Added support for accessing the pre-opened standard file descriptors 0, 1,
+and 2 via the stdfd device driver (major number 0, minor 0, 1, and 2).
+
+---
+Lee -- Mon Jan 26 11:26:14 EST 2004
+
+*Altered the internal interface to pass the xtvec (see .../include/xtio.h) in
+order to support strided-io.
diff --git a/libsysio/Makefile.am b/libsysio/Makefile.am
new file mode 100644 (file)
index 0000000..11e6e3d
--- /dev/null
@@ -0,0 +1,91 @@
+AUTOMAKE_OPTIONS=1.6
+
+if WITH_TESTS
+TESTDIR = tests
+else
+TESTDIR =
+endif
+
+include $(top_srcdir)/src/module.mk 
+include $(top_srcdir)/include/module.mk
+include $(top_srcdir)/tests/module.mk
+include $(top_srcdir)/dev/stdfd/module.mk 
+include $(top_srcdir)/drivers/incore/module.mk 
+include $(top_srcdir)/drivers/native/module.mk 
+include $(top_srcdir)/drivers/yod/module.mk
+include $(top_srcdir)/drivers/sockets/module.mk
+
+lib_LIBRARIES = ${LIBBUILD_DIR}/libsysio.a
+
+if WITH_STDFD_DEV
+OPTIONAL_STDFD_SRCS = $(STDFD_SRCS)
+else
+OPTIONAL_STDFD_SRCS =
+endif
+
+if WITH_INCORE_DRIVER
+OPTIONAL_INCORE_SRCS = $(INCORE_SRCS)
+else
+OPTIONAL_INCORE_SRCS =
+endif
+
+if WITH_NATIVE_DRIVER
+OPTIONAL_NATIVE_SRCS = $(NATIVE_SRCS)
+else
+OPTIONAL_NATIVE_SRCS =
+endif
+
+if WITH_SOCKETS_DRIVER
+OPTIONAL_SOCKETS_SRCS = $(SOCKETS_SRCS)
+else
+OPTIONAL_SOCKETS_SRCS =
+endif
+
+if WITH_CPLANT_YOD
+OPTIONAL_YOD_SRCS = $(YOD_SRCS)
+else
+OPTIONAL_YOD_SRCS =
+endif
+
+if WITH_LUSTRE_HACK
+OPTIONAL_LUSTRE_SRCDIR_SRCS = $(LUSTRE_SRCDIR_SRCS)
+# it would be better that let configure script check this
+AM_CFLAGS = -fPIC
+else
+OPTIONAL_LUSTRE_SRCDIR_SRCS = 
+endif
+
+__LIBBUILD_DIR__libsysio_a_SOURCES = \
+       $(SRCDIR_SRCS) \
+       $(OPTIONAL_LUSTRE_SRCDIR_SRCS) \
+       $(OPTIONAL_STDFD_SRCS) \
+       $(OPTIONAL_INCORE_SRCS) \
+       $(OPTIONAL_SOCKETS_SRCS) \
+       $(OPTIONAL_NATIVE_SRCS) \
+       $(OPTIONAL_YOD_SRCS)
+
+include $(top_srcdir)/Rules.make
+
+EXTRA_DIST = Rules.make misc/init-env.sh $(TESTS_EXTRA) $(SRCDIR_EXTRA) \
+       $(INCLUDE_EXTRA) $(STDFD_EXTRA) $(INCORE_EXTRA) \
+       $(SOCKETS_EXTRA) $(NATIVE_EXTRA) $(YOD_EXTRA)
+
+AM_CPPFLAGS += ${YOD_DRIVER_FLAGS}
+
+really-clean: testsclean maintainer-clean
+       -rm -rf autom4te-2.53.cache
+       -rm -rf .deps
+       -rm -f Makefile.in 
+       -rm -f compile depcomp INSTALL install-sh missing mkinstalldirs \
+               configure aclocal.m4 
+       -rm -f config.guess config.sub
+       -rm -rf $(LIBBUILD_DIR)
+       -rm -f libsysio*.tar.gz
+       cd $(TESTDIR); rm -rf Makefile Makefile.in .deps
+
+tests: $(lib_LIBRARIES) FORCE
+       cd $(TESTDIR); make
+testsclean: FORCE
+       cd $(TESTDIR); make clean
+clean: testsclean clean-am
+FORCE:
diff --git a/libsysio/NEWS b/libsysio/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libsysio/README b/libsysio/README
new file mode 100644 (file)
index 0000000..76b9b97
--- /dev/null
@@ -0,0 +1,66 @@
+Build
+-----
+
+To bootstrap configuration:
+
+sh autogen.sh
+./configure [options]
+
+Without the supported "--with" options only the core sysio library is
+built.
+
+Option --with-native-driver=yes will cause the "native" host name space test
+driver to be enabled and made available in drivers/native/libsysio_native.a
+when built. This is set by default; Use "no" to disable.
+
+Option --with-tests=yes will cause the test programs in the tests directory
+to be enabled. This is set by default; Use "no" to disable.
+
+Option --with-automount=<automount-file-name> will cause automount support
+to be included. If <automount-file-name> is not supplied, a default value
+of ".mount" will be used, matching the Lustre documentation.
+
+To build:
+
+Just `make' it.
+
+Automounts
+----------
+
+For a full description of this see the "Lustre Book" at:
+       <http://www.lustre.org/docs/lustre.pdf>
+
+In short, though, whenever a component is being looked up in a directory and
+that directory has the "set-UID" bit set, then the directory is
+searched for a special file. By default, that file is called ".mount" but
+you may set it to any name using the --with-automount option described
+earlier.
+
+If the content of that file has something formatted, exactly:
+
+<file-system-type>:<source>
+
+Then the <source> description is mounted on the directory containing the
+special automount file and being used as the parent in the lookup. If the
+mount is successful, the parent is replaced with the newly mounted directory
+and processing continues. If the mount fails, or the automount file
+does not exist or cannot be read, everything continues as though the operation
+had never been attempted.
+
+File systems, or volumes, or file-sets, or whatever they are called, that
+have been automounted may also be automatically unmounted when resource
+is required. They are not on a timer, unless the file system driver implements
+one for them. They just disappear as resource is needed elsewhere. As they
+were automatically mounted to begin with, they should re-establish as needed,
+transparently.
+
+REDSTORM
+--------
+
+The following works for me:
+
+#!/bin/sh
+
+export CFLAGS="-DREDSTORM -nostdinc -isystem /home/lee/REDSTORM/catamount/computeincs/i386 -isystem /home/lee/REDSTORM/catamount/include -g -W -Wall -ansi"
+
+sh configure --with-autmount=".mount" --with-native=yes --with-incore-yes --with-stdfd=yes --with-tests=yes
diff --git a/libsysio/Rules.make b/libsysio/Rules.make
new file mode 100644 (file)
index 0000000..45db68c
--- /dev/null
@@ -0,0 +1,18 @@
+
+if WITH_STDFD_DEV
+STDFD_DEV_CPPFLAGS =-DSTDFD_DEV=1 -I$(top_srcdir)/dev/stdfd
+else
+STFD_DEV_CPPFLAGS =
+endif
+
+if WITH_SOCKETS_DRIVER
+SOCKETS_CPPFLAGS=-DWITH_SOCKETS=1
+else
+SOCKETS_CPPFLAGS=
+endif
+
+DEV_CPPFLAGS = $(STDFD_DEV_CPPFLAGS)
+
+AM_CPPFLAGS = \
+       $(AUTOMOUNT) $(ZERO_SUM_MEMORY) $(DEV_CPPFLAGS) $(SOCKETS_CPPFLAGS) \
+       -I$(top_srcdir)/include 
diff --git a/libsysio/autogen.sh b/libsysio/autogen.sh
new file mode 100755 (executable)
index 0000000..81ad5b6
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+aclocal &&
+automake --add-missing --copy &&
+${AUTOCONF:-autoconf}
diff --git a/libsysio/configure.in b/libsysio/configure.in
new file mode 100644 (file)
index 0000000..9f83269
--- /dev/null
@@ -0,0 +1,427 @@
+AC_INIT(libsysio, 0.1)
+
+AC_CANONICAL_HOST
+
+case "$host_os" in
+  linux*)
+       ;;
+  *)
+       AC_MSG_WARN('***' ${host_os}: Unsupported OS target)
+       ;;
+esac
+
+AM_INIT_AUTOMAKE([subdir-objects])
+AM_PROG_CC_C_O
+
+AC_PROG_CC
+AC_PROG_RANLIB
+AC_PROG_MAKE_SET
+AC_HEADER_STDC
+AC_HEADER_STAT
+AC_HEADER_TIME
+
+have_lib_dir=yes;
+AC_ARG_WITH(lib-dir,
+  AC_HELP_STRING([--with-lib-dir=<sysio lib build directory>],
+  [directory for sysio library]),
+  [     case "${withval}" in
+         "yes"|"no"|"") have_lib_dir=no ;;
+         *) LIBBUILD_DIR=${withval};
+            test -d ${LIBBUILD_DIR} || mkdir ${LIBBUILD_DIR} ||
+                have_lib_dir=no;;
+        esac;],
+  [ LIBBUILD_DIR=`pwd`/lib;
+    test -d ${LIBBUILD_DIR} || mkdir ${LIBBUILD_DIR} || have_lib_dir=no;])
+if test x${have_lib_dir} = xyes; then
+  echo "Using sysio library directory ${LIBBUILD_DIR}"
+else
+  AC_MSG_ERROR(Need writeable path to sysio library directory ${LIBBUILD_DIR})
+fi
+AC_SUBST(LIBBUILD_DIR)
+
+AC_ARG_WITH(native_driver,
+  AC_HELP_STRING([--with-native-driver],[build native test driver]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-native-driver) ;;
+       esac;],
+  [with_native_driver=yes;])
+AM_CONDITIONAL(WITH_NATIVE_DRIVER, test x$with_native_driver = xyes)
+
+AC_ARG_WITH(incore-driver,
+  AC_HELP_STRING([--with-incore-driver],[build incore test driver]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-incore-driver) ;;
+       esac],
+  [with_incore_driver=yes])
+AM_CONDITIONAL(WITH_INCORE_DRIVER, test x$with_incore_driver = xyes)
+
+AC_ARG_WITH(tests,
+  AC_HELP_STRING([--with-tests],[build tests]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-tests) ;;
+       esac],
+  [with_tests=yes])
+AM_CONDITIONAL(WITH_TESTS, test x$with_tests = xyes)
+
+AC_ARG_WITH(automount,
+  AC_HELP_STRING([--with-automount@<:@=<automount-file-name>@:>@],
+    [with automounts @<:@<automount-file-name>=.mount@:>@]),
+  [    if test x${withval} = xyes; then
+        AUTOMOUNT=-DAUTOMOUNT_FILE_NAME="\\\".mount\\\"" 
+       elif test x${withval} != x; then
+        AUTOMOUNT=-DAUTOMOUNT_FILE_NAME="\\\"${withval}\\\""
+       fi])
+AC_SUBST(AUTOMOUNT)
+
+AC_ARG_WITH(stdfd-dev,
+  AC_HELP_STRING([--with-stdfd-dev],
+    [build standard file descriptors pseudo-driver]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-stdfd-dev) ;;
+       esac],
+  [with_stdfd_dev=yes])
+AM_CONDITIONAL(WITH_STDFD_DEV, test x$with_stdfd_dev = xyes)
+
+AC_ARG_WITH(zero-sum-memory,
+  AC_HELP_STRING([--with-zero-sum-memory],
+    [free all dynamically allocated memory at the end -- useful for debugging]),
+  [    case "${withval}" in
+        yes) ZERO_SUM_MEMORY=-DZERO_SUM_MEMORY=1 ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-zero-sum-memory) ;;
+       esac],
+  [with_zero_sum_memory=no])
+AC_SUBST(ZERO_SUM_MEMORY)
+
+AC_ARG_WITH(cplant_yod,
+   AC_HELP_STRING([--with-cplant-yod],[build cplant yod I/O driver]),
+   [   case "${withval}" in    
+       yes) if test x${with_stdfd_dev} != xyes; then
+               with_stdfd_dev=yes
+               AM_CONDITIONAL(WITH_STDFD_DEV, test x$with_stdfd_dev = xyes)
+            fi ;;
+       no) ;;
+       *) AC_MSG_ERROR(bad value ${withval} for --with-cplant-yod);;
+       esac],
+    [with_cplant_yod=no])
+AM_CONDITIONAL(WITH_CPLANT_YOD, test x$with_cplant_yod = xyes)
+
+AC_ARG_WITH(cplant_tests,
+   AC_HELP_STRING([--with-cplant-tests=<cplant-build-path>],
+     [build libsysio tests for cplant platform]),
+   [   case "${withval}" in
+       yes) AC_MSG_ERROR(need path to compiler for --with-cplant-tests);;
+       no)  with_cplant_tests=no;;
+       *) CC=${withval}
+          CCDEPMODE=${CC} 
+          CPP="${CC} -E"
+          AC_CHECK_FILE(${CC},
+               [ if test x${with_cplant_yod} != xyes; then
+                       with_cplant_yod=yes
+                       AM_CONDITIONAL(WITH_CPLANT_YOD, test x$with_cplant_yod = xyes)
+                 fi],
+               [ AC_MSG_ERROR(path not found ${CC} for --with-cplant-tests) ]);;
+       esac],
+    [with_cplant_tests=no])
+AM_CONDITIONAL(WITH_CPLANT_TESTS, test x$with_cplant_tests != xno)
+
+AC_ARG_WITH(sockets,
+  AC_HELP_STRING([--with-sockets],
+    [build sockets interface driver (EXPERIMENTAL)]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-sockets) ;;
+       esac],
+  [with_sockets=no])
+AM_CONDITIONAL(WITH_SOCKETS_DRIVER, test x$with_sockets = xyes)
+
+AC_ARG_WITH(lustre-hack,
+  AC_HELP_STRING([--with-lustre-hack],
+    [have hacking code which needed to support liblustre driver (EXPERIMENTAL)]),
+  [    case "${withval}" in
+        yes) ;;
+        no) ;;
+        *) AC_MSG_ERROR(bad value ${withval} for --with-lustre-hack) ;;
+       esac],
+  [with_lustre_hack=no])
+AM_CONDITIONAL(WITH_LUSTRE_HACK, test x$with_lustre_hack = xyes)
+if test x$with_lustre_hack = xyes; then
+       AC_DEFINE(HAVE_LUSTRE_HACK)
+fi
+
+# We keep the original values in `$config_*' and never modify them, so we
+# can write them unchanged into config.make.  Everything else uses
+# $machine, $vendor, and $os, and changes them whenever convenient.
+config_machine=$host_cpu config_vendor=$host_vendor config_os=$host_os
+
+# Don't allow vendor == "unknown"
+test "$config_vendor" = unknown && config_vendor=
+config_os="`echo $config_os | sed 's/^unknown-//'`"
+
+# Some configurations imply other options.
+case "$host_os" in
+  gnu* | linux* | bsd4.4* | netbsd* | freebsd*)
+       # These systems always use GNU tools.
+       gnu_ld=yes gnu_as=yes ;;
+esac
+case "$host_os" in
+  # i586-linuxaout is mangled into i586-pc-linux-gnuaout
+  linux*ecoff* | linux*aout* | gnu*aout* | gnu*ecoff*)
+       ;;
+  gnu* | linux* | freebsd* | netbsd* | sysv4* | solaris2* | irix6*)
+       # These systems (almost) always use the ELF format.
+       elf=yes
+       ;;
+  aix*)
+       # These systems are always xcoff
+       xcoff=yes
+       elf=no
+       ;;
+esac
+
+machine=$config_machine
+vendor=$config_vendor
+os=$config_os
+
+# config.guess on some IBM machines says `rs6000' instead of `powerpc'.
+# Unify this here.
+if test "$machine" = rs6000; then
+       machine="powerpc"
+fi
+
+# If we can't provoke the declaration of stat64 then we assume the
+# environment supports 64-bit file support naturally. Beware!
+AC_MSG_CHECKING(whether _LARGEFILE64_SOURCE definition is required)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>], [
+struct stat64 st64;],
+sysio_largefile64_source_required=no,
+sysio_largefile64_source_required=maybe)
+if test x$sysio_largefile64_source_required = xmaybe; then
+       AC_TRY_COMPILE([
+#define _LARGEFILE64_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>], [
+struct stat64 st64;],
+                      sysio_largefile64_source_required=yes,
+                      sysio_largefile64_source_required=no)
+fi
+AC_MSG_RESULT($sysio_largefile64_source_required)
+if test x$sysio_largefile64_source_required = xyes; then
+       AC_DEFINE(_LARGEFILE64_SOURCE)
+fi
+
+# Alpha linux defines 
+# 
+AC_MSG_CHECKING(for alpha linux)
+alpha_linux_env=no
+if test `expr ${machine} : "alpha"` = 5 && \
+   test `expr ${os} : "linux"` = 5; then
+       alpha_linux_env=yes
+       AC_DEFINE(ALPHA_LINUX)
+fi
+AC_MSG_RESULT($alpha_linux_env)
+AM_CONDITIONAL(TEST_ALPHA_ARG, test x$alpha_linux_env = xyes)
+
+# check for 64 bit stat, fstat, truncate, ftruncate syscalls
+# 
+AC_MSG_CHECKING(for 64 bit stat and truncate syscalls)
+AC_TRY_COMPILE([
+#include <sys/stat.h>
+#include <syscall.h>
+extern int syscall();],
+[char path[] = "/";
+int fd = 0;
+struct stat buf;
+syscall(SYS_stat64,path,&buf);
+syscall(SYS_fstat64,fd,&buf);
+syscall(SYS_truncate64, path, buf.st_size);
+syscall(SYS_ftruncate64, fd, buf.st_size);
+],
+       sysstat64_exists=yes,
+       sysstat64_exists=no)
+AC_MSG_RESULT($sysstat64_exists)
+if test x$sysstat64_exists = xno; then
+       AC_DEFINE(USE_NATIVE_STAT)
+fi
+
+# Check for fdatasync syscall
+#
+AC_MSG_CHECKING(for fdatasync system call)
+if test x$alpha_linux_env = xyes; then
+       _syscallnum=SYS_osf_fdatasync
+else
+       _syscallnum=SYS_fdatasync
+fi
+AC_TRY_COMPILE([
+#include <syscall.h>
+extern int syscall();],
+[int fd = 0;
+syscall(SYS_fdatasync, fd);],
+       syscall_fdatasync_exists=yes,
+       syscall_fdatasync_exists=no)
+AC_MSG_RESULT($syscall_fdatasync_exists)
+if test x$syscall_fdatasync_exists = xyes; then
+       AC_DEFINE_UNQUOTED(NATIVE_FDATASYNC, $_syscallnum)
+fi
+
+# Check for SYS_utime
+#
+AC_MSG_CHECKING(for utime system call)
+AC_TRY_COMPILE([
+#include <syscall.h>
+extern int syscall();],
+[syscall(SYS_utime);],
+       syscall_utime_exists=yes,
+       syscall_utime_exists=no)
+AC_MSG_RESULT($syscall_utime_exists)
+if test x$syscall_utime_exists = xno; then
+       AC_DEFINE(USE_NATIVE_UTIME)
+fi
+# Check for __st_ino 
+#
+AC_MSG_CHECKING(for __st_ino)
+AC_TRY_COMPILE([
+#include <sys/stat.h>],
+[struct stat st;
+st.__st_ino = 0;],
+       have__st_ino=yes,
+       have__st_ino=no)
+AC_MSG_RESULT($have__st_ino)
+if test x$have__st_ino = xyes; then
+       AC_DEFINE(HAVE__ST_INO)
+fi
+
+# Check for st_gen 
+#
+AC_MSG_CHECKING(for st_gen)
+AC_TRY_COMPILE([
+#include <sys/stat.h>],
+[struct stat st;
+st.st_gen = 0;],
+       have_st_gen=yes,
+       have_st_gen=no)
+AC_MSG_RESULT($have_st_gen)
+if test x$have_st_gen = xyes; then
+       AC_DEFINE(HAVE_GENERATION)
+fi
+
+AC_MSG_CHECKING(whether .text pseudo-op must be used)
+AC_CACHE_VAL(sysio_asm_dot_text, [dnl
+cat > conftest.s <<EOF
+       .text
+EOF
+       sysio_asm_dot_text=
+       if ${CC-cc} $CFLAGS -c conftest.s 2>/dev/null; then
+               sysio_asm_dot_text=.text
+       fi
+       rm -f conftest*])
+if test -z "$sysio_dot_text"; then
+       AC_MSG_RESULT(no)
+else
+       AC_MSG_RESULT(yes)
+fi
+
+AC_CACHE_CHECK(for assembler global-symbol directive,
+  sysio_asm_global_directive, [dnl
+sysio_asm_global_directive=UNKNOWN
+for ac_globl in .globl .global .EXPORT; do
+       cat > conftest.s <<EOF
+               ${sysio_asm_dot_text}
+               ${ac_globl} foo
+foo:
+EOF
+       if ${CC-cc} $CFLAGS -c conftest.s 2>/dev/null; then
+       sysio_asm_global_directive=${ac_globl}
+       fi
+       rm -f conftest*
+       test $sysio_asm_global_directive != UNKNOWN && break
+done])
+if test $sysio_asm_global_directive = UNKNOWN; then
+       AC_MSG_ERROR(cannot determine asm global directive)
+#else
+#      AC_DEFINE_UNQUOTED(ASM_GLOBAL_DIRECTIVE, ${sysio_asm_global_directive})
+fi
+
+AC_CACHE_CHECK(for .set assembler directive,
+  sysio_asm_set_directive, [dnl
+cat > conftest.s<<EOF
+${sysio_asm_dot_text}
+foo:
+.set bar, foo
+${sysio_asm_global_directive} bar
+EOF
+       # The alpha-dec-osf1 assembler gives only a warning for `.set'
+       # (but it doesn't work), so we must do a linking check to be sure.
+cat > conftest1.c <<EOF
+extern int bar;
+main () { printf ("%d\n", bar); }
+EOF
+       if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
+          -o conftest conftest.s conftest1.c 1>&AC_FD_CC 2>&AC_FD_CC; then
+               sysio_asm_set_directive=yes
+       else
+               sysio_asm_set_directive=no
+       fi
+       rm -f conftest*])
+#if test $sysio_asm_set_directive = yes; then
+#      AC_DEFINE(HAVE_ASM_SET_DIRECTIVE)
+#fi
+
+AC_CACHE_CHECK(for assembler .weak directive, sysio_asm_weak_directive,
+              [dnl
+cat > conftest.s <<EOF
+${sysio_dot_text}
+foo:
+.weak foo
+EOF
+       if ${CC-cc} $CFLAGS -c conftest.s 2>/dev/null; then
+               sysio_asm_weak_directive=yes
+       else
+               sysio_asm_weak_directive=no
+       fi
+       rm -f conftest*])
+
+if test $sysio_asm_weak_directive = no; then
+       AC_CACHE_CHECK(for assembler .weakext directive,
+                      sysio_asm_weakext_directive, [dnl
+cat > conftest.s <<EOF
+${sysio_dot_text}
+${sysio_asm_global_directive} foo
+foo:
+.weakext bar foo
+.weakext baz
+${sysio_asm_global_directive} baz
+baz:
+EOF
+               if ${CC-cc} $CFLAGS -c conftest.s 2>/dev/null; then
+                       sysio_asm_weakext_directive=yes
+               else
+                       sysio_asm_weakext_directive=no
+               fi
+               rm -f conftest*])
+fi # no .weak
+
+if test x$sysio_asm_weak_directive = xyes; then
+       AC_DEFINE(HAVE_ASM_WEAK_DIRECTIVE)
+fi
+if test x$sysio_asm_weakext_directive = xyes; then
+       AC_DEFINE(HAVE_ASM_WEAKEXT_DIRECTIVE)
+fi
+
+AC_OUTPUT(
+       Makefile
+       tests/Makefile)
+
diff --git a/libsysio/dev/stdfd/module.mk b/libsysio/dev/stdfd/module.mk
new file mode 100644 (file)
index 0000000..ad034fb
--- /dev/null
@@ -0,0 +1,2 @@
+STDFD_SRCS  = dev/stdfd/stdfd.c
+STDFD_EXTRA = dev/stdfd/stdfd.h dev/stdfd/module.mk
diff --git a/libsysio/dev/stdfd/stdfd.c b/libsysio/dev/stdfd/stdfd.c
new file mode 100644 (file)
index 0000000..5a14e8b
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#ifdef __linux__
+#define _BSD_SOURCE
+#endif
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include "sysio.h"
+#include "inode.h"
+#include "dev.h"
+
+#include "stdfd.h"
+
+#ifdef CPLANT_YOD
+#include <sys/statfs.h>
+#include "cplant-yod.h"
+#define dowrite(f, b, n) write_yod(f, b, n)
+#define doread(f, b, n) read_yod(f, b, n)
+#else
+#define dowrite(f, b, n) syscall(SYS_write, f, b, n)
+#define doread(f, b, n) syscall(SYS_read, f, b, n)
+#endif
+
+/*
+ * Pre-opened standard file descriptors driver.
+ */
+
+static int stdfd_open(struct pnode *pno, int flags, mode_t mode);
+static int stdfd_close(struct inode *ino);
+static int stdfd_read(struct inode *ino, struct ioctx *ioctx);
+static int stdfd_write(struct inode *ino, struct ioctx *ioctx);
+static int stdfd_iodone(struct ioctx *ioctx);
+static int stdfd_datasync(struct inode *ino);
+static int stdfd_ioctl(struct inode *ino,
+                      unsigned long int request,
+                      va_list ap);
+
+int
+_sysio_stdfd_init()
+{
+       struct inode_ops stdfd_operations;
+
+       stdfd_operations = _sysio_nodev_ops;
+       stdfd_operations.inop_open = stdfd_open;
+       stdfd_operations.inop_close = stdfd_close;
+       stdfd_operations.inop_read = stdfd_read;
+       stdfd_operations.inop_write = stdfd_write;
+       stdfd_operations.inop_iodone = stdfd_iodone;
+       stdfd_operations.inop_datasync = stdfd_datasync;
+       stdfd_operations.inop_ioctl = stdfd_ioctl;
+
+       return _sysio_char_dev_register(SYSIO_C_STDFD_MAJOR,
+                                       "stdfd",
+                                       &stdfd_operations);
+}
+
+static int
+stdfd_open(struct pnode *pno __IS_UNUSED,
+          int flags __IS_UNUSED,
+          mode_t mode __IS_UNUSED)
+{
+
+       return 0;
+}
+
+static int
+stdfd_close(struct inode *ino __IS_UNUSED)
+{
+
+       return 0;
+}
+
+static int
+doio(ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, struct inode *),
+     struct inode *ino,
+     struct ioctx *ioctx)
+{
+
+       if (ioctx->ioctx_xtvlen != 1) {
+               /*
+                * No scatter/gather to "file" address space (we're not
+                * seekable) and "nowhere" makes no sense.
+                */
+               return -EINVAL;
+       }
+       ioctx->ioctx_cc =
+           _sysio_doio(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
+                       ioctx->ioctx_iov, ioctx->ioctx_iovlen,
+                       (ssize_t (*)(void *, size_t, _SYSIO_OFF_T, void *))f,
+                       ino);
+       if (ioctx->ioctx_cc < 0) {
+               ioctx->ioctx_errno = -ioctx->ioctx_cc;
+               ioctx->ioctx_cc = -1;
+       }
+       return 0;
+}
+
+static ssize_t
+stdfd_read_simple(void *buf,
+                 size_t nbytes,
+                 _SYSIO_OFF_T off __IS_UNUSED,
+                 struct inode *ino)
+{
+
+       int     fd = SYSIO_MINOR_DEV(ino->i_rdev);
+
+       return doread(fd, buf, nbytes);
+}
+
+static int
+stdfd_read(struct inode *ino, struct ioctx *ioctx)
+{
+
+       return doio(stdfd_read_simple, ino, ioctx);
+}
+
+static ssize_t
+stdfd_write_simple(const void *buf,
+                  size_t nbytes,
+                  _SYSIO_OFF_T off __IS_UNUSED,
+                  struct inode *ino)
+{
+       int     fd = SYSIO_MINOR_DEV(ino->i_rdev);
+
+       return dowrite(fd, buf, nbytes);
+}
+
+static int
+stdfd_write(struct inode *ino, struct ioctx *ioctx)
+{
+
+       return doio((ssize_t (*)(void *,
+                                size_t,
+                                _SYSIO_OFF_T,
+                                struct inode *))stdfd_write_simple,
+                   ino,
+                   ioctx);
+}
+
+static int
+stdfd_iodone(struct ioctx *iocp __IS_UNUSED)
+{
+
+       /*
+        * It's always done in this driver. It completed when posted.
+        */
+       return 1;
+}
+
+static int
+stdfd_datasync(struct inode *ino __IS_UNUSED)
+{
+
+       /*
+        * We don't buffer, so nothing to do.
+        */
+       return 0;
+}
+
+static int
+stdfd_ioctl(struct inode *ino __IS_UNUSED,
+           unsigned long int request __IS_UNUSED,
+           va_list ap __IS_UNUSED)
+{
+
+       return -ENOTTY;
+}
diff --git a/libsysio/dev/stdfd/stdfd.h b/libsysio/dev/stdfd/stdfd.h
new file mode 100644 (file)
index 0000000..3bac7c1
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Std{in,out,err} pseudo-device-driver support.
+ */
+
+#define SYSIO_C_STDFD_MAJOR    0
+
+extern int _sysio_stdfd_init(void);
diff --git a/libsysio/drivers/incore/README b/libsysio/drivers/incore/README
new file mode 100644 (file)
index 0000000..2f8c4b8
--- /dev/null
@@ -0,0 +1,27 @@
+This "incore" file system driver is a self-contained file system. It does
+not use any resource external to the node.
+
+It is primarily intended for enabling an efficient compute-node bootstrap. It
+might also be useful for a very small scratch file system, holding device
+files, and the like.
+
+The root directory i-node is manufactured on the fly. The source specification
+for the mount() call should be something like:
+
+       <perms>+<uid>+<gid>
+
+Where:
+       <perms>         are the directory permissions masked by 0777
+                       Note -- no umask is applied.
+       <uid>           should be the owner's uid
+       <gid>           should be the owner's gid
+
+Most operations are supported, with the notable exception of symbolic
+links.
+
+In the implementation, the driver is really set up to export most
+useful symbols without polluting the name space or contending with
+other public symbols. However, the symbols are not yet exported. If
+we ever require a proc-fs style file system, this could be very useful
+provided a little extra work is done to allow other drivers to overload
+some operations. Particularly the file ops, I would think.
diff --git a/libsysio/drivers/incore/fs_incore.c b/libsysio/drivers/incore/fs_incore.c
new file mode 100644 (file)
index 0000000..b6eb1c0
--- /dev/null
@@ -0,0 +1,1693 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#ifdef __linux__
+#define _BSD_SOURCE
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#ifdef _HAVE_STATVFS
+#include <sys/statvfs.h>
+#endif
+#include <sys/queue.h>
+
+#include "sysio.h"
+#include "fs.h"
+#include "mount.h"
+#include "inode.h"
+#include "dev.h"
+
+#include "fs_incore.h"
+
+
+/*
+ * In-core file system pseudo-driver.
+ */
+
+/*
+ * Pseudo-blocksize.
+ */
+#define INCORE_BLKSIZE         (8192)
+
+/*
+ * Format of an incore inode.
+ */
+struct incore_inode {
+       LIST_ENTRY(incore_inode) ici_link;              /* i-nodes list link */
+       unsigned ici_revalidate                 : 1;    /* synch sys inode? */
+       struct intnl_stat ici_st;                       /* attrs */
+       struct file_identifier ici_fileid;              /* file ID */
+       void    *ici_data;                              /* file data */
+};
+
+/*
+ * Given pointer to inode, return pointer to incore-inode.
+ */
+#define I2IC(ino)      ((struct incore_inode *)(ino)->i_private)
+
+struct incore_filesys {
+       LIST_HEAD(, incore_inode) icfs_icinodes;        /* all i-nodes list */
+};
+
+/*
+ * Given pointer to filesys, return pointer to incore-filesys.
+ */
+#define FS2ICFS(fs)    ((struct incore_filesys *)(fs)->fs_private)
+
+static int _sysio_incore_fsswop_mount(const char *source,
+                                     unsigned flags,
+                                     const void *data,
+                                     struct pnode *tocover,
+                                     struct mount **mntp);
+
+static struct fssw_ops incore_fssw_ops = {
+               _sysio_incore_fsswop_mount
+};
+
+static void _sysio_incore_fsop_gone(struct filesys *fs);
+
+static struct filesys_ops incore_fs_ops = {
+               _sysio_incore_fsop_gone,
+};
+
+static int _sysio_incore_dirop_lookup(struct pnode *pno,
+                                     struct inode **inop,
+                                     struct intent *intnt,
+                                     const char *path);
+static int _sysio_incore_inop_getattr(struct pnode *pno,
+                                     struct inode *ino,
+                                     struct intnl_stat *stbuf);
+static int _sysio_incore_inop_setattr(struct pnode *pno,
+                                     struct inode *ino,
+                                     unsigned mask,
+                                     struct intnl_stat *stbuf);
+static ssize_t _sysio_incore_dirop_getdirentries(struct inode *ino,
+                                          char *buf,
+                                          size_t nbytes,
+                                          _SYSIO_OFF_T *basep);
+static int _sysio_incore_dirop_mkdir(struct pnode *pno, mode_t mode);
+static int _sysio_incore_dirop_rmdir(struct pnode *pno);
+static int _sysio_incore_inop_open(struct pnode *pno, int flags, mode_t mode);
+static int _sysio_incore_inop_close(struct inode *ino);
+static int _sysio_incore_dirop_link(struct pnode *old, struct pnode *new);
+static int _sysio_incore_dirop_unlink(struct pnode *pno);
+static int _sysio_incore_dirop_rename(struct pnode *old, struct pnode *new);
+static int _sysio_incore_filop_read(struct inode *ino, struct ioctx *ioctx);
+static int _sysio_incore_filop_write(struct inode *ino, struct ioctx *ioctx);
+static _SYSIO_OFF_T _sysio_incore_filop_pos(struct inode *ino,
+                                           _SYSIO_OFF_T off);
+static int _sysio_incore_filop_iodone(struct ioctx *ioctx);
+static int _sysio_incore_filop_fcntl(struct inode *ino, int cmd, va_list ap);
+static int _sysio_incore_inop_sync(struct inode *ino);
+static int _sysio_incore_filop_ioctl(struct inode *ino,
+                                   unsigned long int request,
+                                   va_list ap);
+static int _sysio_incore_dirop_mknod(struct pnode *pno, mode_t mode, dev_t dev);
+#ifdef _HAVE_STATVFS
+static int _sysio_incore_inop_statvfs(struct pnode *pno,
+                                     struct inode *ino,
+                                     struct intnl_statvfs *buf);
+#endif
+static void _sysio_incore_inop_gone(struct inode *ino);
+
+#define _sysio_incore_dirop_symlink \
+       (int (*)(struct pnode *, const char *))_sysio_do_enosys
+#define _sysio_incore_dirop_readlink \
+       (int (*)(struct pnode *, char *, size_t))_sysio_do_einval
+#define _sysio_incore_dirop_read \
+       (int (*)(struct inode *, \
+                struct ioctx *))_sysio_do_eisdir
+#define _sysio_incore_dirop_write \
+       (int (*)(struct inode *, \
+                struct ioctx *))_sysio_do_eisdir
+#define _sysio_incore_dirop_pos \
+       (_SYSIO_OFF_T (*)(struct inode *, \
+                         _SYSIO_OFF_T))_sysio_do_eisdir
+#define _sysio_incore_dirop_iodone \
+       (int (*)(struct ioctx *))_sysio_do_illop
+#define _sysio_incore_dirop_fcntl \
+       (int (*)(struct inode *, int, va_list))_sysio_do_eisdir
+#define _sysio_incore_dirop_ioctl \
+       (int (*)(struct inode *, \
+                unsigned long int, \
+                va_list))_sysio_do_eisdir
+
+static struct inode_ops _sysio_incore_dir_ops = {
+       _sysio_incore_dirop_lookup,
+       _sysio_incore_inop_getattr,
+       _sysio_incore_inop_setattr,
+       _sysio_incore_dirop_getdirentries,
+       _sysio_incore_dirop_mkdir,
+       _sysio_incore_dirop_rmdir,
+       _sysio_incore_dirop_symlink,
+       _sysio_incore_dirop_readlink,
+       _sysio_incore_inop_open,
+       _sysio_incore_inop_close,
+       _sysio_incore_dirop_link,
+       _sysio_incore_dirop_unlink,
+       _sysio_incore_dirop_rename,
+       _sysio_incore_dirop_read,
+       _sysio_incore_dirop_write,
+       _sysio_incore_dirop_pos,
+       _sysio_incore_dirop_iodone,
+       _sysio_incore_dirop_fcntl,
+       _sysio_incore_inop_sync,
+       _sysio_incore_inop_sync,
+       _sysio_incore_dirop_ioctl,
+       _sysio_incore_dirop_mknod,
+#ifdef _HAVE_STATVFS
+       _sysio_incore_inop_statvfs,
+#endif
+       _sysio_incore_inop_gone
+};
+
+#define _sysio_incore_filop_lookup \
+       (int (*)(struct pnode *, \
+                struct inode **, \
+                struct intent *, \
+                const char *))_sysio_do_illop
+#define _sysio_incore_filop_getdirentries \
+       (ssize_t (*)(struct inode *, \
+                char *, \
+                size_t, \
+                _SYSIO_OFF_T *))_sysio_do_illop
+#define _sysio_incore_filop_mkdir \
+       (int (*)(struct pnode *, mode_t))_sysio_do_illop
+#define _sysio_incore_filop_rmdir \
+       (int (*)(struct pnode *))_sysio_do_illop
+#define _sysio_incore_filop_symlink \
+       (int (*)(struct pnode *, const char *))_sysio_do_illop
+#define _sysio_incore_symlinkop_readlink \
+       (int (*)(struct pnode *, char *, size_t))_sysio_do_illop
+#define _sysio_incore_filop_link \
+       (int (*)(struct pnode *old, struct pnode *new))_sysio_do_illop
+#define _sysio_incore_filop_unlink \
+       (int (*)(struct pnode *pno))_sysio_do_illop
+#define _sysio_incore_filop_rename \
+       (int (*)(struct pnode *old, struct pnode *new))_sysio_do_illop
+#define _sysio_incore_filop_mknod \
+       (int (*)(struct pnode *pno, mode_t, dev_t))_sysio_do_illop
+
+static struct inode_ops _sysio_incore_file_ops = {
+       _sysio_incore_filop_lookup,
+       _sysio_incore_inop_getattr,
+       _sysio_incore_inop_setattr,
+       _sysio_incore_filop_getdirentries,
+       _sysio_incore_filop_mkdir,
+       _sysio_incore_filop_rmdir,
+       _sysio_incore_filop_symlink,
+       _sysio_incore_symlinkop_readlink,
+       _sysio_incore_inop_open,
+       _sysio_incore_inop_close,
+       _sysio_incore_filop_link,
+       _sysio_incore_filop_unlink,
+       _sysio_incore_filop_rename,
+       _sysio_incore_filop_read,
+       _sysio_incore_filop_write,
+       _sysio_incore_filop_pos,
+       _sysio_incore_filop_iodone,
+       _sysio_incore_filop_fcntl,
+       _sysio_incore_inop_sync,
+       _sysio_incore_inop_sync,
+       _sysio_incore_filop_ioctl,
+       _sysio_incore_filop_mknod,
+#ifdef _HAVE_STATVFS
+       _sysio_incore_inop_statvfs,
+#endif
+       _sysio_incore_inop_gone
+};
+
+static struct inode_ops _sysio_incore_dev_ops = {
+       _sysio_incore_filop_lookup,
+       _sysio_incore_inop_getattr,
+       _sysio_incore_inop_setattr,
+       _sysio_incore_filop_getdirentries,
+       _sysio_incore_filop_mkdir,
+       _sysio_incore_filop_rmdir,
+       _sysio_incore_filop_symlink,
+       _sysio_incore_symlinkop_readlink,
+       _sysio_nodev_inop_open,
+       _sysio_nodev_inop_close,
+       _sysio_incore_filop_link,
+       _sysio_incore_filop_unlink,
+       _sysio_incore_filop_rename,
+       _sysio_nodev_inop_read,
+       _sysio_nodev_inop_write,
+       _sysio_nodev_inop_pos,
+       _sysio_nodev_inop_iodone,
+       _sysio_incore_filop_fcntl,
+       _sysio_incore_inop_sync,
+       _sysio_nodev_inop_sync,
+       _sysio_nodev_inop_ioctl,
+       _sysio_incore_filop_mknod,
+#ifdef _HAVE_STATVFS
+       _sysio_incore_inop_statvfs,
+#endif
+       _sysio_incore_inop_gone
+};
+
+typedef void *(*probe_ty)(void *data, size_t len, void *arg);
+
+/*
+ * Lookup data argument bundle record.
+ */
+struct lookup_data {
+       struct qstr *name;                              /* desired entry name */
+       struct intnl_dirent *de;                        /* last dirent */
+       size_t  minsiz;                                 /* min hole needed */
+       struct {
+               void    *p;                             /* best hole */
+               size_t  len;                            /* best hole len */
+       } hole;
+};
+
+/*
+ * Initialize lookup data argument bundle.
+ */
+#define INCORE_LD_INIT(ld, minsz, qs) \
+       do { \
+               (ld)->name = (qs); \
+               (ld)->de = NULL; \
+               (ld)->minsiz = (minsz); \
+               (ld)->hole.p = NULL; \
+               (ld)->hole.len = 0; \
+       } while (0)
+
+/*
+ * Calculate size of a directory entry given length of the entry name.
+ */
+#define INCORE_D_RECLEN(namlen) \
+       (((size_t )&((struct intnl_dirent *)0)->d_name + \
+         (namlen) + 1 + sizeof(void *)) & \
+        ~(sizeof(void *) - 1))
+
+/*
+ * Given mode bits, return directory entry type code.
+ */
+#define INCORE_D_TYPEOF(m)     (((m) & S_IFMT) >> 12)
+
+static char incore_dir_template[INCORE_D_RECLEN(1) + INCORE_D_RECLEN(2)];
+#if 0
+static struct intnl_dirent incore_dir_template[] = {
+       {
+               0,
+               INCORE_D_RECLEN(1),
+               INCORE_D_RECLEN(1),
+               INCORE_D_TYPEOF(S_IFDIR),
+               { '.', '\0' }
+       },
+       {
+               0,
+               INCORE_D_RECLEN(1) + INCORE_D_RECLEN(2),
+               INCORE_D_RECLEN(2),
+               INCORE_D_TYPEOF(S_IFDIR),
+               { '.', '.', '\0' }
+       }
+};
+#endif
+
+/*
+ * Initialize this driver.
+ */
+int
+_sysio_incore_init()
+{
+       struct intnl_dirent *de;
+       off_t   off;
+
+       /*
+        * Fill in the directory template.
+        */
+       de = (struct intnl_dirent *)incore_dir_template;
+#ifdef _DIRENT_HAVE_D_OFF
+       de->d_off =
+#endif
+           off = de->d_reclen = INCORE_D_RECLEN(1);
+       de->d_type = INCORE_D_TYPEOF(S_IFDIR);
+       de->d_name[0] = '.';
+#ifdef _DIRENT_HAVE_D_NAMLEN
+       de->d_namlen = 1;
+#endif
+       /*
+        * Move to entry for `..'
+        */
+       de = (struct intnl_dirent *)((char *)de + off);
+       de->d_reclen = INCORE_D_RECLEN(2);
+#ifdef _DIRENT_HAVE_D_NAMLEN
+       de->d_namlen = 2;
+#endif
+#ifdef _DIRENT_HAVE_D_OFF
+       de->d_off =
+#endif
+           off += de->d_reclen;
+       de->d_type = INCORE_D_TYPEOF(S_IFDIR);
+       de->d_name[0] = de->d_name[1] = '.';
+       de->d_name[2] = ' ';
+
+       return _sysio_fssw_register("incore", &incore_fssw_ops);
+}
+
+static ino_t
+incore_inum_alloc()
+{
+       static ino_t nxtnum = 1;
+
+       assert(nxtnum);
+       return nxtnum++;
+}
+
+static struct incore_inode *
+incore_i_alloc(struct incore_filesys *icfs, struct intnl_stat *st)
+{
+       struct incore_inode *icino;
+
+       assert(st->st_ino);
+       assert(!st->st_size);
+
+       icino = malloc(sizeof(struct incore_inode));
+       if (!icino)
+               return NULL;
+       icino->ici_revalidate = 0;
+       icino->ici_st = *st;
+       icino->ici_fileid.fid_data = &icino->ici_st.st_ino;
+       icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);
+       icino->ici_data = NULL;
+
+       LIST_INSERT_HEAD(&icfs->icfs_icinodes, icino, ici_link);
+
+       return icino;
+}
+
+static int
+incore_trunc(struct incore_inode *icino, _SYSIO_OFF_T size, int clear)
+{
+       _SYSIO_OFF_T n;
+       void    *p;
+
+       if (size < 0) 
+               return -EINVAL;
+       n = size;
+       if (!size) {
+               if (icino->ici_data) {
+                       free(icino->ici_data);
+                       icino->ici_data = NULL;
+               }
+               n = 0;
+               goto out;
+       }
+       p = realloc(icino->ici_data, (size_t )n);
+       if (!p)
+               return -ENOSPC;
+       icino->ici_data = p;
+       if (clear && n > icino->ici_st.st_size)
+               (void )memset((char *)icino->ici_data + icino->ici_st.st_size,
+                             0,
+                             (size_t )(n - icino->ici_st.st_size));
+out:
+       icino->ici_st.st_size = n;
+       icino->ici_st.st_blocks =
+           (n + icino->ici_st.st_blksize - 1) / icino->ici_st.st_blksize;
+       icino->ici_st.st_mtime = time(NULL);
+       return 0;
+}
+
+static void
+incore_i_destroy(struct incore_inode *icino)
+{
+
+       LIST_REMOVE(icino, ici_link);
+       (void )incore_trunc(icino, 0, 0);
+       free(icino);
+}
+
+static struct incore_inode *
+incore_directory_new(struct incore_filesys *icfs,
+                    struct incore_inode *parent,
+                    struct intnl_stat *st)
+{
+       struct incore_inode *icino;
+       int     err;
+       struct intnl_dirent *de;
+
+       icino = incore_i_alloc(icfs, st);
+       if (!icino)
+               return NULL;
+
+       if (!parent)
+               parent = icino;                         /* root */
+
+       /*
+        * Allocate and init directory data.
+        */
+       err = incore_trunc(icino, sizeof(incore_dir_template), 1);
+       if (err) {
+               incore_i_destroy(icino);
+               return NULL;
+       }
+       (void )memcpy(icino->ici_data,
+                     &incore_dir_template,
+                     sizeof(incore_dir_template));
+       de = icino->ici_data;
+       de->d_ino = st->st_ino;
+       de =
+           (struct intnl_dirent *)((char *)de +
+#ifdef _DIRENT_HAVE_D_OFF
+                                   de->d_off
+#else
+                                   de->d_reclen
+#endif
+                                   );
+       de->d_ino = parent->ici_st.st_ino;
+
+       /*
+        * Set creation time to modify time set by truncate.
+        */
+       st->st_ctime = st->st_mtime;
+
+       return icino;
+}
+
+static int
+_sysio_incore_fsswop_mount(const char *source,
+                          unsigned flags,
+                          const void *data __IS_UNUSED,
+                          struct pnode *tocover,
+                          struct mount **mntp)
+{
+       char    *cp;
+       unsigned long ul;
+       long    l;
+       mode_t  mode;
+       uid_t   uid;
+       gid_t   gid;
+       int     err;
+       dev_t   dev;
+       struct intnl_stat stat;
+       struct incore_filesys *icfs;
+       ino_t   inum;
+       struct incore_inode *icino;
+       struct filesys *fs;
+       struct inode *rooti;
+       struct pnode_base *rootpb;
+       struct mount *mnt;
+       static struct qstr noname = { NULL, 0, 0 };
+
+       /*
+        * Source is a specification for the root attributes of this
+        * new file system in the format:
+        *
+        * <permissions>+<owner>+<group>
+        */
+       ul = strtoul(source, &cp, 0);
+       mode = (mode_t )ul & 07777;
+       if (*cp != '+' ||
+           (ul == ULONG_MAX && errno == ERANGE) ||
+           (unsigned long)mode != ul ||
+           mode > 07777)
+               return -EINVAL;
+       source = cp;
+       l = strtol(source, &cp, 0);
+       uid = (uid_t )l;
+       if (*cp != '+' ||
+           ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
+           (long )uid != l)
+               return -EINVAL;
+       source = cp;
+       l = strtol(source, &cp, 0);
+       gid = (gid_t )l;
+       if (*cp ||
+           ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
+           (long )gid != l)
+               return -EINVAL;
+
+       err = 0;
+
+       dev = _sysio_dev_alloc();
+
+       mnt = NULL;
+       rootpb = NULL;
+       rooti = NULL;
+       fs = NULL;
+       icino = NULL;
+       icfs = NULL;
+
+       /*
+        * Create new FS.
+        */
+       icfs = malloc(sizeof(struct incore_filesys));
+       if (!icfs) {
+               err = -ENOMEM;
+               goto error;
+       }
+       (void )memset(icfs, 0, sizeof(struct incore_filesys));
+       LIST_INIT(&icfs->icfs_icinodes);
+
+       /*
+        * Create root i-node.
+        */
+       (void )memset(&stat, 0, sizeof(stat));
+       stat.st_dev = dev;
+       inum = incore_inum_alloc();
+#ifdef HAVE__ST_INO
+       stat.__st_ino = inum; 
+#endif
+       stat.st_mode = S_IFDIR | (mode & 07777);
+       stat.st_nlink = 2;
+       stat.st_uid = uid;
+       stat.st_gid = gid;
+       stat.st_size = 0;
+       stat.st_blksize = INCORE_BLKSIZE;
+       stat.st_blocks = 0;
+       stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
+       stat.st_ino = inum;
+       icino = incore_directory_new(icfs, NULL, &stat);
+       if (!icino)
+               return -ENOSPC;
+       icino->ici_st.st_atime = icino->ici_st.st_mtime;
+
+       fs =
+           _sysio_fs_new(&incore_fs_ops,
+                         (flags & MOUNT_F_RO) ? FS_F_RO : 0,
+                         icfs);
+       if (!fs) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Create root for system.
+        *
+        * Persistent across remounts because we ask for immunity.
+        */
+       rooti =
+           _sysio_i_new(fs,
+                        &icino->ici_fileid,
+                        icino->ici_st.st_mode,
+                        0,
+                        1,
+                        &_sysio_incore_dir_ops,
+                        icino);
+       if (!rooti) {
+               err = -ENOMEM;
+               goto error;
+       }
+       rootpb = _sysio_pb_new(&noname, NULL, rooti);
+       if (!rootpb) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Have path-node specified by the given source argument. Let the
+        * system finish the job, now.
+        */
+       mnt = NULL;
+       err =
+           _sysio_do_mount(fs,
+                           rootpb,
+                           flags,
+                           tocover,
+                           &mnt);
+       if (err)
+               goto error;
+
+       *mntp = mnt;
+
+       goto out;
+
+error:
+       if (mnt && _sysio_do_unmount(mnt) != 0)
+                       abort();
+       if (rootpb) {
+               _sysio_pb_gone(rootpb);
+               rooti = NULL;
+       }
+       if (rooti)
+               I_RELE(rooti);
+       if (fs) {
+               FS_RELE(fs);
+               goto out;
+       }
+       if (icino) {
+               incore_i_destroy(icino);
+               goto out;
+       }
+       if (icfs) {
+               free(icfs);
+               goto out;
+       }
+
+out:
+       return err;
+}
+
+static void
+_sysio_incore_fsop_gone(struct filesys *fs)
+{
+       struct incore_filesys *icfs;
+       struct incore_inode *icino, *oicino;
+
+       icfs = FS2ICFS(fs);
+
+       /*
+        * Free up i-node resource associated with this file system.
+        */
+       icino = icfs->icfs_icinodes.lh_first;
+       while (icino) {
+               oicino = icino;
+               icino = icino->ici_link.le_next;
+               incore_i_destroy(oicino);
+       }
+
+       /*
+        * Free the FS record.
+        */
+       free(icfs);
+}
+
+/*
+ * A directory search engine. Various functions are carried out by
+ * supplying appropriate callback functions.
+ *
+ * The two arguments, entry and hole, are called, if not null, for each
+ * directory entry and hole, respectively.
+ */
+static void *
+incore_directory_probe(void *data,
+                      size_t siz,
+                      _SYSIO_OFF_T origin
+#ifndef _DIRENT_HAVE_D_OFF
+                               __IS_UNUSED
+#endif
+                      ,
+                      probe_ty entry,
+                      probe_ty hole,
+                      void *arg)
+{
+       struct intnl_dirent *de;
+       void    *p;
+       size_t  n;
+
+       de = data;
+       for (;;) {
+#ifdef _DIRENT_HAVE_D_OFF
+               assert(de->d_off);
+#else
+               assert(de->d_reclen);
+#endif
+               if (entry && (p = (*entry)(de, de->d_reclen, arg)))
+                       return p;
+               n =
+#ifdef _DIRENT_HAVE_D_OFF
+                   de->d_off - origin;
+#else
+                   ((void *)de - data) + de->d_reclen;
+#endif
+               if (hole) {
+                       p = (*hole)((void *)de, de->d_reclen, arg);
+                       if (p)
+                               return p;
+               }
+               if (n >= siz)
+                       break;
+               de = (struct intnl_dirent *)((char *)data + n);
+       }
+
+       return NULL;
+}
+
+static struct intnl_dirent *
+incore_directory_match(struct intnl_dirent *de,
+                      size_t reclen __IS_UNUSED,
+                      struct lookup_data *ld)
+{
+
+#if defined(BSD) || defined(REDSTORM)
+       if (IFTODT(de->d_type) == DT_WHT)
+               return NULL;
+#endif
+       if (
+#ifdef _DIRENT_HAVE_D_NAMLEN
+           ld->name->len == de->d_namlen &&
+#endif
+           strncmp(de->d_name, ld->name->name, ld->name->len) == 0)
+               return de;
+       ld->de = de;
+       return NULL;
+}
+
+static int
+_sysio_incore_dirop_lookup(struct pnode *pno,
+                          struct inode **inop,
+                          struct intent *intnt __IS_UNUSED,
+                          const char *path __IS_UNUSED)
+{
+       struct inode *ino;
+       struct intnl_dirent *de;
+       struct incore_inode *icino;
+       struct lookup_data lookup_data;
+       struct file_identifier fileid;
+#ifdef notdef
+       struct inode_ops *ops;
+#endif
+
+       /*
+        * Revalidate?
+        */
+       if (*inop) {
+               icino = I2IC(*inop);
+               assert(icino);
+               if (icino->ici_revalidate) {
+                       (*inop)->i_mode = icino->ici_st.st_mode;
+                       icino->ici_revalidate = 0;
+               }
+               return 0;
+       }
+
+       ino = pno->p_parent->p_base->pb_ino;
+       icino = I2IC(ino);
+       INCORE_LD_INIT(&lookup_data,
+                      ULONG_MAX,
+                      &pno->p_base->pb_name);
+       de =
+           incore_directory_probe(icino->ici_data,
+                                  icino->ici_st.st_size,
+                                  0,
+                                  (probe_ty )incore_directory_match,
+                                  NULL,
+                                  &lookup_data);
+       if (!de)
+               return -ENOENT;
+
+       fileid.fid_data = &de->d_ino;
+       fileid.fid_len = sizeof(de->d_ino);
+       ino =
+           _sysio_i_find(ino->i_fs, &fileid);
+#ifdef notdef
+       if (ino)
+               goto out;
+       icino->ici_fileid.fid_data = &icino->ici_st.st_ino;
+       icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);
+       ops = NULL;
+       switch (icino->ici_st.st_mode & S_IFMT) {
+       case S_IFDIR:
+               ops = &_sysio_incore_dir_ops;
+               break;
+       case S_IFREG:
+               ops = &_sysio_incore_file_ops;
+               break;
+       default:
+               break;
+       }
+       if (!ops)
+               abort();
+       ino =
+           _sysio_i_new(ino->i_fs,
+                        &icino->ici_fileid,
+                        icino->ici_st.st_mode,
+                        0,
+                        1,
+                        ops,
+                        icino);
+#endif
+       if (!ino)
+               return -ENOMEM;
+
+#ifdef notdef
+out:
+#endif
+       *inop = ino;
+       return 0;
+}
+
+static int
+_sysio_incore_inop_getattr(struct pnode *pno,
+                          struct inode *ino,
+                          struct intnl_stat *stbuf)
+{
+       struct incore_inode *icino;
+
+       if (!ino)
+               ino = pno->p_base->pb_ino;
+       icino = I2IC(ino);
+       *stbuf = icino->ici_st;
+       return 0;
+}
+
+static int
+_sysio_incore_inop_setattr(struct pnode *pno,
+                          struct inode *ino,
+                          unsigned mask,
+                          struct intnl_stat *stbuf)
+{
+       struct incore_inode *icino;
+       int     err;
+
+       if (!ino)
+               ino = pno->p_base->pb_ino;
+       if (!ino)
+               return -EBADF;
+       icino = I2IC(ino);
+
+       err = 0;
+       if (mask & SETATTR_LEN) {
+               err = incore_trunc(icino, stbuf->st_size, 1);
+               if (err)
+                       goto out;
+               mask &= ~SETATTR_LEN;
+       }
+       if (mask & SETATTR_MODE) {
+               icino->ici_st.st_mode =
+                   (icino->ici_st.st_mode & S_IFMT) | (stbuf->st_mode & 07777);
+               icino->ici_revalidate = 1;
+       }
+       if (mask & SETATTR_MTIME)
+               icino->ici_st.st_mtime = stbuf->st_mtime;
+       if (mask & SETATTR_ATIME)
+               icino->ici_st.st_atime = stbuf->st_atime;
+       if (mask & SETATTR_UID)
+               icino->ici_st.st_uid = stbuf->st_uid;
+       if (mask & SETATTR_GID)
+               icino->ici_st.st_gid = stbuf->st_gid;
+       icino->ici_st.st_ctime = time(NULL);
+
+out:
+       return err;
+}
+
+static void *
+incore_directory_position(struct intnl_dirent *de,
+                         size_t reclen __IS_UNUSED,
+                         void *p)
+{
+
+       return (void *)de >= p ? de : NULL;
+}
+
+struct copy_info {
+       void    *data;
+       size_t  nbytes;
+};
+
+/*
+ * Eumeration callback.
+ *
+ * Note:
+ * On those systems supporting white-out entries, they are returned. On
+ * systems without, they are not.
+ */
+static void *
+incore_directory_enumerate(struct intnl_dirent *de,
+                          size_t reclen,
+                          struct copy_info *cinfo) {
+
+       if (reclen > cinfo->nbytes)
+               return de;
+       (void *)memcpy(cinfo->data, de, reclen);
+       cinfo->data = (char *)cinfo->data + reclen;
+       cinfo->nbytes -= reclen;
+       return NULL;
+}
+
+static ssize_t
+_sysio_incore_dirop_getdirentries(struct inode *ino,
+                                char *buf,
+                                size_t nbytes,
+                                _SYSIO_OFF_T *basep)
+{
+       struct incore_inode *icino = I2IC(ino);
+       off_t   off;
+       struct intnl_dirent *de;
+       struct copy_info copy_info;
+
+       if (*basep > icino->ici_st.st_size)
+               return 0;
+
+       de =
+           incore_directory_probe(icino->ici_data,
+                                  icino->ici_st.st_size,
+                                  *basep,
+                                  (probe_ty )incore_directory_position,
+                                  NULL,
+                                  (char *)icino->ici_data + *basep);
+       if (!de) {
+               /*
+                * Past EOF.
+                */
+               *basep = 0;
+               return 0;
+       }
+
+       copy_info.data = buf;
+       copy_info.nbytes = nbytes;
+       off = (char *)de - (char *)icino->ici_data;
+       de =
+           incore_directory_probe(de,
+                                  icino->ici_st.st_size - off,
+                                  off,
+                                  (probe_ty )incore_directory_enumerate,
+                                  NULL,
+                                  &copy_info);
+       nbytes -= copy_info.nbytes;
+       icino->ici_st.st_atime = time(NULL);
+       if (!nbytes)
+               return -EOVERFLOW;
+       *basep = nbytes;
+       return (ssize_t )nbytes;
+}
+
+static struct intnl_dirent *
+incore_directory_best_fit(void *data, size_t len, struct lookup_data *ld)
+{
+
+       if (!ld->hole.len || len < ld->hole.len) {
+               ld->hole.p = data;
+               ld->hole.len = len;
+       }
+
+       return NULL;
+}
+
+static int
+incore_directory_insert(struct incore_inode *parent,
+                       struct qstr *name,
+                       ino_t inum,
+                       unsigned char type)
+{
+       size_t  reclen;
+       struct lookup_data lookup_data;
+       struct intnl_dirent *de;
+       size_t  xt;
+       size_t  n;
+       size_t  r;
+
+       reclen = INCORE_D_RECLEN(name->len);
+       INCORE_LD_INIT(&lookup_data, reclen, name);
+       de =
+           incore_directory_probe(parent->ici_data,
+                                  parent->ici_st.st_size,
+                                  0,
+                                  (probe_ty )incore_directory_match,
+                                  (probe_ty )incore_directory_best_fit,
+                                  &lookup_data);
+       if (de)
+               return -EEXIST;
+       de = lookup_data.de;
+       xt = (char *)lookup_data.de - (char *)parent->ici_data;
+       n =
+#ifdef _DIRENT_HAVE_D_OFF
+           de->d_off;
+#else
+           xt + de->d_reclen;
+#endif
+       r =
+#ifdef _DIRENT_HAVE_D_OFF
+           de->d_reclen;
+#else
+           INCORE_D_RECLEN(de->d_namlen);
+#endif
+       if (!parent->ici_st.st_size ||
+           xt + r + reclen > (size_t )parent->ici_st.st_size) {
+               int     err;
+
+               err = incore_trunc(parent, xt + r + reclen, 1);
+               if (err)
+                       return err;
+               de = (struct intnl_dirent *)((char *)parent->ici_data + xt);
+               n = parent->ici_st.st_size;
+       }
+
+#ifdef _DIRENT_HAVE_D_OFF
+       de->d_off = xt + r;                             /* trim */
+#else
+       de->d_reclen = r;
+#endif
+       de = (struct intnl_dirent *)((char *)de + r);                           /* reposition */
+       xt += r;
+
+#ifndef _DIRENT_HAVE_D_OFF
+       /*
+        * Will we split this hole or use all of it?
+        */
+       if (lookup_data.hole.len - reclen &&
+           lookup_data.hole.len - reclen <= INCORE_D_RECLEN(1))
+               reclen = lookup_data.hole.len;
+#endif
+
+       /*
+        * Insert new.
+        */
+       de->d_ino = inum;
+#ifdef _DIRENT_HAVE_D_OFF
+       de->d_off = n;
+#endif
+       de->d_reclen = reclen;
+       de->d_type = type;
+       (void )memcpy(de->d_name, name->name, name->len);
+#ifdef _DIRENT_HAVE_D_NAMLEN
+       de->d_namlen = name->len;
+#endif
+
+#ifndef _DIRENT_HAVE_D_OFF
+       xt += reclen;
+       if (n - xt) {
+               /*
+                * White-out remaining part of the hole.
+                */
+               (void *)de += reclen;
+               de->d_ino = 0;
+               de->d_reclen = n - xt;
+               de->d_type = DT_WHT;
+               de->d_namlen = 0;
+       }
+#endif
+
+       /*
+        * Update attributes to reflect the new entry.
+        */
+       parent->ici_st.st_nlink++;
+       assert(parent->ici_st.st_nlink);
+       parent->ici_st.st_atime = parent->ici_st.st_mtime = time(NULL);
+
+       return 0;
+}
+
+static int
+_sysio_incore_dirop_mkdir(struct pnode *pno, mode_t mode)
+{
+       struct intnl_stat stat;
+       struct incore_inode *icino, *parent;
+       ino_t   inum;
+       int     err;
+       struct intnl_dirent *de = NULL;
+       struct inode *ino;
+
+       ino = pno->p_parent->p_base->pb_ino;
+       parent = I2IC(ino);
+
+       if (!S_ISDIR(parent->ici_st.st_mode))
+               return -ENOTDIR;
+
+       (void )memset(&stat, 0, sizeof(stat));
+       stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
+       inum = incore_inum_alloc();
+#ifdef HAVE__ST_INO
+       stat.__st_ino = inum;
+#endif
+       stat.st_mode = S_IFDIR | (mode & 07777);
+       stat.st_nlink = 2;
+       stat.st_uid = getuid();
+       stat.st_gid = getgid();
+       stat.st_size = 0;
+       stat.st_blksize = 4096;
+       stat.st_blocks = 0;
+       stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
+       stat.st_ino = inum;
+       icino = incore_directory_new(FS2ICFS(ino->i_fs), parent, &stat);
+       if (!icino)
+               return -ENOSPC;
+
+       /*
+        * Tell the system about the new inode.
+        *
+        * Persistent across remounts because we ask for immunity.
+        */
+       ino =
+           _sysio_i_new(pno->p_parent->p_base->pb_ino->i_fs,
+                        &icino->ici_fileid,
+                        stat.st_mode,
+                        0,
+                        1,
+                        &_sysio_incore_dir_ops,
+                        icino);
+       if (!ino) {
+               incore_i_destroy(icino);
+               return -ENOMEM;
+       }
+
+       /*
+        * Insert into parent.
+        */
+       err =
+           incore_directory_insert(parent,
+                                   &pno->p_base->pb_name,
+                                   stat.st_ino,
+                                   INCORE_D_TYPEOF(S_IFDIR));
+
+       if (err) {
+               de->d_ino = 0;                          /* bad parent */
+               I_RELE(ino);
+               _sysio_i_gone(ino);
+               return err;
+       }
+
+       pno->p_base->pb_ino = ino;
+       return 0;
+}
+
+static int
+incore_unlink_entry(struct incore_inode *icino,
+                   struct qstr *name)
+{
+       struct lookup_data lookup_data;
+       struct intnl_dirent *de;
+       size_t  reclen;
+#ifdef _DIRENT_HAVE_D_OFF
+       size_t  off;
+#endif
+
+       if (!S_ISDIR(icino->ici_st.st_mode))
+               return -ENOTDIR;
+
+       INCORE_LD_INIT(&lookup_data, 0, name);
+       de =
+           incore_directory_probe(icino->ici_data,
+                                  icino->ici_st.st_size,
+                                  0,
+                                  (probe_ty )incore_directory_match,
+                                  NULL,
+                                  &lookup_data);
+       if (!de)
+               return -ENOENT;
+       assert((size_t )((char *)de - (char *)icino->ici_data) >=
+              sizeof(incore_dir_template));
+#ifndef _DIRENT_HAVE_D_OFF
+       reclen = de->d_reclen;
+#else
+       off = de->d_off;
+       reclen = off - ((char *)de - (char *)icino->ici_data);
+#endif
+       (void )memset(de, 0, reclen);
+#ifndef _DIRENT_HAVE_D_OFF
+       de->d_type = (__uint8_t )DTTOIF(DT_WHT);
+       de->d_reclen = reclen;
+#else
+       lookup_data.de->d_off = off;
+#endif
+
+       /*
+        * Adjust link count.
+        */
+       assert(icino->ici_st.st_nlink > 2);
+       icino->ici_st.st_nlink--;
+
+       return 0;
+}
+
+static int
+_sysio_incore_dirop_rmdir(struct pnode *pno)
+{
+       struct inode *ino = pno->p_base->pb_ino;
+       struct incore_inode *icino = I2IC(ino);
+       int     err;
+
+       if (!pno->p_base->pb_name.len ||
+           (pno->p_base->pb_name.name[0] == '.' &&
+            (pno->p_base->pb_name.len == 1 ||
+             (pno->p_base->pb_name.len == 2 &&
+              pno->p_base->pb_name.name[1] == '.'))))
+               return -EINVAL;
+
+       if (!S_ISDIR(icino->ici_st.st_mode))
+               return -ENOTDIR;
+
+       if (icino->ici_st.st_nlink > 2)
+               return -ENOTEMPTY;
+
+       pno->p_base->pb_ino = NULL;
+       err =
+           incore_unlink_entry(I2IC(pno->p_parent->p_base->pb_ino),
+                               &pno->p_base->pb_name);
+       return err;
+}
+
+static int
+incore_create(struct pnode *pno, struct intnl_stat *st)
+{
+       struct inode *dino, *ino;
+       struct incore_inode *icino;
+       int     err;
+
+       dino = pno->p_parent->p_base->pb_ino;
+       assert(dino);
+
+       icino = incore_i_alloc(FS2ICFS(dino->i_fs), st);
+       if (!icino)
+               return -ENOSPC;
+
+       /*
+        * Tell the system about the new inode.
+        */
+       ino =
+           _sysio_i_new(dino->i_fs,
+                        &icino->ici_fileid,
+                        st->st_mode,
+                        st->st_rdev,
+                        1,
+                        S_ISREG(st->st_mode)
+                          ? &_sysio_incore_file_ops
+                          : &_sysio_incore_dev_ops,
+                        icino);
+       if (!ino) {
+               incore_i_destroy(icino);
+               return -ENOMEM;
+       }
+
+       /*
+        * Insert into parent.
+        */
+       err =
+           incore_directory_insert(I2IC(dino),
+                                   &pno->p_base->pb_name,
+                                   st->st_ino,
+                                   INCORE_D_TYPEOF(icino->ici_st.st_mode));
+       if (err) {
+               I_RELE(ino);
+               _sysio_i_gone(ino);
+               return err;
+       }
+
+       pno->p_base->pb_ino = ino;
+       return 0;
+}
+
+static int
+_sysio_incore_inop_open(struct pnode *pno, int flags __IS_UNUSED, mode_t mode)
+{
+       struct intnl_stat stat;
+       ino_t   inum;
+
+       /*
+        * File exists. Nothing to do.
+        */
+       if (pno->p_base->pb_ino)
+               return 0;
+
+       /*
+        * Must create a new, regular, file.
+        */
+       (void )memset(&stat, 0, sizeof(stat));
+       stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
+       inum = incore_inum_alloc();
+#ifdef HAVE__ST_INO
+       stat.__st_ino = inum;
+#endif
+       stat.st_mode = S_IFREG | (mode & 07777);
+       stat.st_nlink = 1;
+       stat.st_uid = getuid();
+       stat.st_gid = getgid();
+       stat.st_rdev = 0;
+       stat.st_size = 0;
+       stat.st_blksize = 4096;
+       stat.st_blocks = 0;
+       stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
+       stat.st_ino = inum;
+
+       return incore_create(pno, &stat);
+}
+
+static int
+_sysio_incore_inop_close(struct inode *ino __IS_UNUSED)
+{
+
+       return 0;
+}
+
+static int
+_sysio_incore_dirop_link(struct pnode *old, struct pnode *new)
+{
+       struct incore_inode *icino = I2IC(old->p_base->pb_ino);
+       int     err;
+
+       assert(!new->p_base->pb_ino);
+       assert(!S_ISDIR(old->p_base->pb_ino->i_mode));
+
+       /*
+        * Can bump the link count?
+        */
+       if (!(icino->ici_st.st_nlink + 1))
+               return -EMLINK;
+       /*
+        * Insert into parent.
+        */
+       err =
+           incore_directory_insert(I2IC(new->p_parent->p_base->pb_ino),
+                                   &new->p_base->pb_name,
+                                   icino->ici_st.st_ino,
+                                   INCORE_D_TYPEOF(icino->ici_st.st_mode));
+       if (err)
+               return err;
+       /*
+        * Bump the link count.
+        */
+       icino->ici_st.st_nlink++;
+
+       return 0;
+}
+
+static int
+_sysio_incore_dirop_rename(struct pnode *old, struct pnode *new)
+{
+       int     err;
+       struct incore_inode *icino = I2IC(old->p_base->pb_ino);
+
+       if (new->p_base->pb_ino) {
+               /*
+                * Have to kill off the target first.
+                */
+               if (S_ISDIR(I2IC(new->p_base->pb_ino)->ici_st.st_mode) &&
+                   I2IC(new->p_base->pb_ino)->ici_st.st_nlink > 2)
+                       return -ENOTEMPTY;
+               err =
+                   incore_unlink_entry(I2IC(new->p_parent->p_base->pb_ino),
+                                       &new->p_base->pb_name);
+               if (err)
+                       return err;
+       }
+
+       /*
+        * Insert into new parent.
+        */
+       err =
+           incore_directory_insert(I2IC(new->p_parent->p_base->pb_ino),
+                                   &new->p_base->pb_name,
+                                   icino->ici_st.st_ino,
+                                   INCORE_D_TYPEOF(icino->ici_st.st_mode));
+       if (err)
+               abort();
+       /*
+        * Remove from the old parent.
+        */
+       err =
+           incore_unlink_entry(I2IC(old->p_parent->p_base->pb_ino),
+                               &old->p_base->pb_name);
+       if (err)
+               abort();
+
+       if (S_ISDIR(icino->ici_st.st_mode)) {
+               struct intnl_dirent *de;
+
+               /*
+                * We moved a directory. The entry for `..' must be corrected.
+                */
+               de = icino->ici_data;
+               de++;
+               assert(strcmp(de->d_name, "..") == 0);
+               de->d_ino = I2IC(new->p_parent->p_base->pb_ino)->ici_st.st_ino;
+       }
+       return 0;
+}
+
+static int
+_sysio_incore_dirop_unlink(struct pnode *pno)
+{
+       struct inode *ino = pno->p_base->pb_ino;
+       struct incore_inode *icino = I2IC(ino);
+       int     err;
+
+       if (S_ISDIR(icino->ici_st.st_mode))
+               return -EISDIR;
+
+       err =
+           incore_unlink_entry(I2IC(pno->p_parent->p_base->pb_ino),
+                               &pno->p_base->pb_name);
+       return err;
+}
+
+static int
+doio(ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, struct incore_inode *),
+     struct inode *ino,
+     struct ioctx *ioctx)
+{
+
+       ioctx->ioctx_cc =
+           _sysio_doio(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
+                       ioctx->ioctx_iov, ioctx->ioctx_iovlen,
+                       (ssize_t (*)(void *, size_t, _SYSIO_OFF_T, void *))f,
+                       I2IC(ino));
+       if (ioctx->ioctx_cc  < 0) {
+               ioctx->ioctx_errno = -ioctx->ioctx_cc;
+               ioctx->ioctx_cc = -1;
+       }
+       ioctx->ioctx_done = 1;
+
+       return 0;
+}
+
+static ssize_t
+incore_read(void *buf, size_t nbytes,
+           _SYSIO_OFF_T off,
+           struct incore_inode *icino)
+{
+       size_t  n;
+
+       if (off < 0)
+               return -EINVAL;
+       if (!nbytes || off > icino->ici_st.st_size)
+               return 0;
+       n = icino->ici_st.st_size - (size_t )off;
+       if (n > nbytes)
+               n = nbytes;
+       (void )memcpy(buf, (char *)icino->ici_data + off, (size_t )n);
+
+       return (ssize_t )n;
+}
+
+static int
+_sysio_incore_filop_read(struct inode *ino, struct ioctx *ioctx)
+{
+       
+
+       return doio(incore_read, ino, ioctx);
+}
+
+static ssize_t
+incore_write(const void *buf, size_t nbytes,
+            _SYSIO_OFF_T off,
+            struct incore_inode *icino)
+{
+       _SYSIO_OFF_T pos;
+
+       if (off < 0)
+               return -EINVAL;
+       if (!nbytes || off > icino->ici_st.st_size)
+               return 0;
+       pos = off + nbytes;
+       if (off && pos <= off) {
+               /*
+                * It's all or nothing. We won't write just part of
+                * the buffer.
+                */
+               return -EFBIG;
+       }
+       if (pos > icino->ici_st.st_size) {
+               int     err;
+
+               err = incore_trunc(icino, (size_t )pos, 0);
+               if (err)
+                       return err;
+       }
+       (void )memcpy((char *)icino->ici_data + off, buf, nbytes);
+
+       return (ssize_t )nbytes;
+}
+
+static int
+_sysio_incore_filop_write(struct inode *ino, struct ioctx *ioctx)
+{
+
+       return doio((ssize_t (*)(void *, size_t,
+                                _SYSIO_OFF_T,
+                                struct incore_inode *))incore_write,
+                   ino,
+                   ioctx);
+}
+
+static _SYSIO_OFF_T
+_sysio_incore_filop_pos(struct inode *ino __IS_UNUSED, _SYSIO_OFF_T off)
+{
+
+       return off;
+}
+
+static int
+_sysio_incore_filop_iodone(struct ioctx *iocp __IS_UNUSED)
+{
+
+       /*
+        * It's always done in this driver. It completed when posted.
+        */
+       return 1;
+}
+
+static int
+_sysio_incore_filop_fcntl(struct inode *ino __IS_UNUSED,
+                         int cmd __IS_UNUSED,
+                         va_list ap __IS_UNUSED)
+{
+
+       /*
+        * No fcntl's supported.
+        */
+       return -ENOTTY;
+}
+
+static int
+_sysio_incore_inop_sync(struct inode *ino __IS_UNUSED)
+{
+
+       /*
+        * With what?
+        */
+       return 0;
+}
+
+static int
+_sysio_incore_filop_ioctl(struct inode *ino __IS_UNUSED,
+                         unsigned long int request __IS_UNUSED,
+                         va_list ap __IS_UNUSED)
+{
+
+       /*
+        * No ioctl's supported.
+        */
+       return -ENOTTY;
+}
+
+static int
+_sysio_incore_dirop_mknod(struct pnode *pno, mode_t mode, dev_t dev)
+{
+       mode_t  m;
+       struct intnl_stat stat;
+       ino_t   inum;
+
+       assert(!pno->p_base->pb_ino);
+
+       m = mode & S_IFMT;
+       if (S_ISCHR(m))
+               m &= ~S_IFCHR;
+       else if (S_ISFIFO(m))
+               m &= ~S_IFIFO;
+       else if (S_ISBLK(m))
+               m &= ~S_IFCHR;
+       else
+               return -EINVAL;
+       if (m)
+               return -EINVAL;
+
+       /*
+        * Initialize attributes.
+        */
+       (void )memset(&stat, 0, sizeof(stat));
+       stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
+       inum = incore_inum_alloc();
+#ifdef HAVE__ST_INO
+       stat.__st_ino = inum;
+#endif
+       stat.st_mode = mode;
+       stat.st_nlink = 1;
+       stat.st_uid = getuid();
+       stat.st_gid = getgid();
+       stat.st_rdev = dev;
+       stat.st_size = 0;
+       stat.st_blksize = 4096;
+       stat.st_blocks = 0;
+       stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
+       stat.st_ino = inum;
+
+       return incore_create(pno, &stat);
+}
+
+#ifdef _HAVE_STATVFS
+static int
+_sysio_incore_inop_statvfs(struct pnode *pno,
+                          struct inode *ino,
+                          struct intnl_statvfs *buf)
+{
+       struct filesys *fs;
+
+       if (!ino)
+               ino = pno->p_base->pb_ino;
+       assert(ino);
+
+       fs = pno->p_base->pb_ino->i_fs;
+
+       (void )memset(buf, 0, sizeof(struct intnl_statvfs));
+
+       /*
+        * Mostly, we lie.
+        */
+       buf->f_bsize = fs->fs_bsize;
+       buf->f_frsize = buf->f_bsize;
+       buf->f_blocks = ~0;
+       buf->f_blocks /= buf->f_bsize;
+       buf->f_bfree = buf->f_blocks - 1;
+       buf->f_bavail = buf->f_bfree;
+       buf->f_files = buf->f_blocks;
+       buf->f_ffree = buf->f_files - 1;
+       buf->f_favail = buf->f_ffree;
+       buf->f_fsid = fs->fs_id;
+       buf->f_flag = 0;
+       buf->f_namemax = ULONG_MAX;
+
+       return 0;
+}
+#endif
+
+void
+_sysio_incore_inop_gone(struct inode *ino)
+{
+       struct incore_inode *icino = I2IC(ino);
+
+       incore_i_destroy(icino);
+}
diff --git a/libsysio/drivers/incore/fs_incore.h b/libsysio/drivers/incore/fs_incore.h
new file mode 100644 (file)
index 0000000..84fa631
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Native file system driver support.
+ */
+
+extern int _sysio_incore_init(void);
diff --git a/libsysio/drivers/incore/module.mk b/libsysio/drivers/incore/module.mk
new file mode 100644 (file)
index 0000000..140d69b
--- /dev/null
@@ -0,0 +1,2 @@
+INCORE_SRCS  = drivers/incore/fs_incore.c
+INCORE_EXTRA = drivers/incore/fs_incore.h drivers/incore/module.mk
diff --git a/libsysio/drivers/native/fs_native.c b/libsysio/drivers/native/fs_native.c
new file mode 100644 (file)
index 0000000..c66c1ed
--- /dev/null
@@ -0,0 +1,1722 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2004 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#ifdef __linux__
+#define _BSD_SOURCE
+#endif
+
+#include <stdio.h>                                     /* for NULL */
+#include <stdlib.h>
+#ifdef __linux__
+#include <string.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#if 0
+#include <sys/vfs.h>
+#endif
+#ifdef _HAVE_STATVFS
+#include <sys/statvfs.h>
+#include <sys/statfs.h>
+#endif
+#include <utime.h>
+#include <sys/queue.h>
+#if !(defined(REDSTORM) || defined(MAX_IOVEC))
+#include <limits.h>
+#endif
+
+#include "sysio.h"
+#include "fs.h"
+#include "mount.h"
+#include "inode.h"
+#include "xtio.h"
+
+#include "fs_native.h"
+
+#ifdef REDSTORM
+#include <sys/uio.h>
+#endif
+
+#if defined(SYS_getdirentries)
+#define DIR_STREAMED 0
+#define DIR_CVT_64 0
+#elif defined(SYS_getdents64)
+#define DIR_STREAMED 1
+#define DIR_CVT_64 0
+#elif defined(SYS_getdents)
+#define DIR_STREAMED 1
+#if defined(_LARGEFILE64_SOURCE)
+#define DIR_CVT_64 1
+/*
+ * Kernel version of directory entry.
+ */
+struct linux_dirent {
+       unsigned long ld_ino;
+       unsigned long ld_off;
+       unsigned short ld_reclen;
+       char    ld_name[1];
+};
+#include <dirent.h>
+#else /* !defined(_LARGEFILE64_SOURCE) */
+#define DIR_CVT_64 0
+#endif /* defined(_LARGEFILE64_SOURCE) */
+#else /* catch-none */
+#error No usable directory fill entries interface available
+#endif
+
+/*
+ * Local host file system driver.
+ */
+
+#if defined(ALPHA_LINUX)
+
+/* stat struct from asm/stat.h, as returned 
+ * by alpha linux kernel
+ */
+struct __native_stat {
+       unsigned int    st_dev;
+       unsigned int    st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_rdev;
+       long            st_size;
+       unsigned long   st_atime;
+       unsigned long   st_mtime;
+       unsigned long   st_ctime;
+       unsigned int    st_blksize;
+       int             st_blocks;
+       unsigned int    st_flags;
+       unsigned int    st_gen;
+};
+
+#define COPY_STAT(src, dest)                    \
+do {                                            \
+       memset((dest), 0, sizeof((*dest)));     \
+       (dest)->st_dev     = (src)->st_dev;     \
+       (dest)->st_ino     = (src)->st_ino;     \
+       (dest)->st_mode    = (src)->st_mode;    \
+       (dest)->st_nlink   = (src)->st_nlink;   \
+       (dest)->st_uid     = (src)->st_uid;     \
+       (dest)->st_gid     = (src)->st_gid;     \
+       (dest)->st_rdev    = (src)->st_rdev;    \
+       (dest)->st_size    = (src)->st_size;    \
+       (dest)->st_atime   = (src)->st_atime;   \
+       (dest)->st_mtime   = (src)->st_mtime;   \
+       (dest)->st_ctime   = (src)->st_ctime;   \
+       (dest)->st_blksize = (src)->st_blksize; \
+       (dest)->st_blocks  = (src)->st_blocks;  \
+       (dest)->st_flags   = (src)->st_flags;   \
+       (dest)->st_gen     = (src)->st_gen;     \
+} while (0);
+
+#else 
+#define __native_stat intnl_stat
+#define COPY_STAT(src, dest) *(dest) = *(src) 
+#endif
+
+#if defined(USE_NATIVE_STAT)
+#define __SYS_STAT SYS_lstat
+#define __SYS_FSTAT SYS_fstat
+#define __SYS_TRUNCATE SYS_truncate
+#define __SYS_FTRUNCATE SYS_ftruncate
+#else
+#define __SYS_STAT SYS_lstat64
+#define __SYS_FSTAT SYS_fstat64
+#define __SYS_TRUNCATE SYS_truncate64
+#define __SYS_FTRUNCATE SYS_ftruncate64
+#endif
+
+#if defined(USE_NATIVE_FDATASYNC)
+#define __SYS_FDATASYNC SYS_osf_fdatasync
+#else
+#define __SYS_FDATASYNC SYS_fdatasync
+#endif
+
+#if defined(USE_NATIVE_UTIME)
+#define __SYS_UTIME SYS_utimes
+#else
+#define __SYS_UTIME SYS_utime
+#endif
+
+/*
+ * Native file identifiers format.
+ */
+struct native_inode_identifier {
+       dev_t   dev;                                    /* device number */
+       ino_t   ino;                                    /* i-number */
+#ifdef HAVE_GENERATION
+       unsigned int gen;                               /* generation number */
+#endif
+};
+
+/*
+ * Driver-private i-node information we keep about local host file
+ * system objects.
+ */
+struct native_inode {
+       unsigned
+               ni_seekok               : 1;            /* can seek? */
+       struct native_inode_identifier ni_ident;        /* unique identifier */
+       struct file_identifier ni_fileid;               /* ditto */
+       int     ni_fd;                                  /* host fildes */
+       int     ni_oflags;                              /* flags, from open */
+       unsigned ni_nopens;                             /* soft ref count */
+       _SYSIO_OFF_T ni_fpos;                           /* current pos */
+};
+
+/*
+ * Native IO path arguments.
+ */
+struct native_io {
+       char    nio_op;                                 /* 'r' or 'w' */
+       struct native_inode *nio_nino;                  /* native ino */
+};
+
+static int native_inop_lookup(struct pnode *pno,
+                             struct inode **inop,
+                             struct intent *intnt,
+                             const char *path);
+static int native_inop_getattr(struct pnode *pno,
+                              struct inode *ino,
+                              struct intnl_stat *stbuf);
+static int native_inop_setattr(struct pnode *pno,
+                              struct inode *ino,
+                              unsigned mask,
+                              struct intnl_stat *stbuf);
+static ssize_t native_getdirentries(struct inode *ino,
+                                   char *buf,
+                                   size_t nbytes,
+                                   _SYSIO_OFF_T *basep);
+static int native_inop_mkdir(struct pnode *pno, mode_t mode);
+static int native_inop_rmdir(struct pnode *pno);
+static int native_inop_symlink(struct pnode *pno, const char *data);
+static int native_inop_readlink(struct pnode *pno, char *buf, size_t bufsiz);
+static int native_inop_open(struct pnode *pno, int flags, mode_t mode);
+static int native_inop_close(struct inode *ino);
+static int native_inop_link(struct pnode *old, struct pnode *new);
+static int native_inop_unlink(struct pnode *pno);
+static int native_inop_rename(struct pnode *old, struct pnode *new);
+static int native_inop_read(struct inode *ino, struct ioctx *ioctx);
+static int native_inop_write(struct inode *ino, struct ioctx *ioctx);
+static _SYSIO_OFF_T native_inop_pos(struct inode *ino, _SYSIO_OFF_T off);
+static int native_inop_iodone(struct ioctx *ioctx);
+static int native_inop_fcntl(struct inode *ino, int cmd, va_list ap);
+static int native_inop_sync(struct inode *ino);
+static int native_inop_datasync(struct inode *ino);
+static int native_inop_ioctl(struct inode *ino,
+                            unsigned long int request,
+                            va_list ap);
+static int native_inop_mknod(struct pnode *pno, mode_t mode, dev_t dev);
+#ifdef _HAVE_STATVFS
+static int native_inop_statvfs(struct pnode *pno,
+                              struct inode *ino,
+                              struct intnl_statvfs *buf);
+#endif
+static void native_inop_gone(struct inode *ino);
+
+static struct inode_ops native_i_ops = {
+       native_inop_lookup,
+       native_inop_getattr,
+       native_inop_setattr,
+       native_getdirentries,
+       native_inop_mkdir,
+       native_inop_rmdir,
+       native_inop_symlink,
+       native_inop_readlink,
+       native_inop_open,
+       native_inop_close,
+       native_inop_link,
+       native_inop_unlink,
+       native_inop_rename,
+       native_inop_read,
+       native_inop_write,
+       native_inop_pos,
+       native_inop_iodone,
+       native_inop_fcntl,
+       native_inop_sync,
+       native_inop_datasync,
+       native_inop_ioctl,
+       native_inop_mknod,
+#ifdef _HAVE_STATVFS
+       native_inop_statvfs,
+#endif
+       native_inop_gone
+};
+
+static int native_fsswop_mount(const char *source,
+                              unsigned flags,
+                              const void *data,
+                              struct pnode *tocover,
+                              struct mount **mntp);
+
+static struct fssw_ops native_fssw_ops = {
+       native_fsswop_mount
+};
+
+static void native_fsop_gone(struct filesys *fs);
+
+static struct filesys_ops native_inodesys_ops = {
+       native_fsop_gone,
+};
+
+/*
+ * This example driver plays a strange game. It maintains a private,
+ * internal mount -- It's own separate, rooted, name space. The local
+ * file system's entire name space is available via this tree.
+ *
+ * This simplifies the implementation. At mount time, we need to generate
+ * a path-node to be used as a root. This allows us to look up the needed
+ * node in the host name space and leverage a whole lot of support from
+ * the system.
+ */
+static struct mount *native_internal_mount = NULL;
+
+/*
+ * Given i-node, return driver private part.
+ */
+#define I2NI(ino)      ((struct native_inode *)((ino)->i_private))
+
+/*
+ * stat -- by path.
+ */
+static int
+native_stat(const char *path, struct intnl_stat *buf)
+{
+       int     err;
+       struct __native_stat stbuf;
+
+       err = syscall(__SYS_STAT, path, &stbuf);
+       if (err)
+               err = -errno;
+       COPY_STAT(&stbuf, buf);
+
+       return err;
+}
+
+/*
+ * stat -- by fildes
+ */
+static int
+native_fstat(int fd, struct intnl_stat *buf)
+{
+       int     err;
+       struct __native_stat stbuf;
+
+       err = syscall(__SYS_FSTAT, fd, &stbuf);
+       if (err)
+               err = -errno;
+       COPY_STAT(&stbuf, buf);
+
+       return err;
+}
+
+/*
+ * Introduce an i-node to the system.
+ */
+static struct inode *
+native_i_new(struct filesys *fs, struct intnl_stat *buf)
+{
+       struct native_inode *nino;
+       struct inode *ino;
+
+       nino = malloc(sizeof(struct native_inode));
+       if (!nino)
+               return NULL;
+       bzero(&nino->ni_ident, sizeof(nino->ni_ident));
+       nino->ni_ident.dev = buf->st_dev;
+       nino->ni_ident.ino = buf->st_ino;
+#ifdef HAVE_GENERATION
+       nino->ni_ident.gen = buf->st_gen;
+#endif
+       nino->ni_fileid.fid_data = &nino->ni_ident;
+       nino->ni_fileid.fid_len = sizeof(nino->ni_ident);
+       nino->ni_fd = -1;
+       nino->ni_oflags = 0;
+       nino->ni_nopens = 0;
+       nino->ni_fpos = 0;
+       ino =
+           _sysio_i_new(fs,
+                        &nino->ni_fileid,
+#ifndef AUTOMOUNT_FILE_NAME
+                        buf->st_mode & S_IFMT,
+#else
+                        buf->st_mode,                  /* all of the bits! */
+#endif
+                        0,
+                        0,
+                        &native_i_ops,
+                        nino);
+       if (!ino)
+               free(nino);
+       return ino;
+}
+
+/*
+ * Initialize this driver.
+ */
+int
+_sysio_native_init()
+{
+
+       /*
+        * Capture current process umask and reset our process umask to
+        * zero. All permission bits to open/creat/setattr are absolute --
+        * They've already had a umask applied, when appropriate.
+        */
+       _sysio_umask = syscall(SYS_umask, 0);
+
+       return _sysio_fssw_register("native", &native_fssw_ops);
+}
+
+/*
+ * Create private, internal, view of the hosts name space.
+ */
+static int
+create_internal_namespace()
+{
+       int     err;
+       struct mount *mnt;
+       struct inode *rootino;
+       struct pnode_base *rootpb;
+       static struct qstr noname = { NULL, 0, 0 };
+       struct filesys *fs;
+       struct intnl_stat stbuf;
+
+       if (native_internal_mount) {
+               /*
+                * Reentered!
+                */
+               abort();
+       }
+
+       /*
+        * We maintain an artificial, internal, name space in order to
+        * have access to fully qualified path names in the various routines.
+        * Initialize that name space now.
+        */
+       mnt = NULL;
+       rootino = NULL;
+       rootpb = NULL;
+       fs = _sysio_fs_new(&native_inodesys_ops, 0, NULL);
+       if (!fs) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Get root i-node.
+        */
+       err = native_stat("/", &stbuf);
+       if (err)
+               goto error;
+       rootino = native_i_new(fs, &stbuf);
+       if (!rootino) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Generate base path-node for root.
+        */
+       rootpb = _sysio_pb_new(&noname, NULL, rootino);
+       if (!rootpb) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Mount it. This name space is disconnected from the
+        * rest of the system -- Only available within this driver.
+        */
+       err = _sysio_do_mount(fs, rootpb, 0, NULL, &mnt);
+       if (err)
+               goto error;
+
+       native_internal_mount = mnt;
+       return 0;
+error:
+       if (mnt) {
+               if (_sysio_do_unmount(mnt) != 0)
+                       abort();
+               fs = NULL;
+               rootpb = NULL;
+               rootino = NULL;
+       }
+       if (rootpb)
+               _sysio_pb_gone(rootpb);
+       if (fs) {
+               FS_RELE(fs);
+               _sysio_fs_gone(fs);
+       }
+
+       return err;
+}
+
+static int
+native_fsswop_mount(const char *source,
+                   unsigned flags,
+                   const void *data __IS_UNUSED,
+                   struct pnode *tocover,
+                   struct mount **mntp)
+{
+       int     err;
+       struct nameidata nameidata;
+       struct mount *mnt;
+
+       /*
+        * Caller must use fully qualified path names when specifying
+        * the source.
+        */
+       if (*source != '/')
+               return -ENOENT;
+
+       if (!native_internal_mount) {
+               err = create_internal_namespace();
+               if (err)
+                       return err;
+       }
+
+       /*
+        * Lookup the source in the internally maintained name space.
+        */
+       ND_INIT(&nameidata, 0, source, native_internal_mount->mnt_root, NULL);
+       err = _sysio_path_walk(native_internal_mount->mnt_root, &nameidata);
+       if (err)
+               return err;
+
+       /*
+        * Have path-node specified by the given source argument. Let the
+        * system finish the job, now.
+        */
+       err =
+           _sysio_do_mount(native_internal_mount->mnt_fs,
+                           nameidata.nd_pno->p_base,
+                           flags,
+                           tocover,
+                           &mnt);
+       /*
+        * Release the internal name space pnode and clean up any
+        * aliases we might have generated. We really don't need to cache them
+        * as they are only used at mount time..
+        */
+       P_RELE(nameidata.nd_pno);
+       (void )_sysio_p_prune(native_internal_mount->mnt_root);
+
+       if (!err) {
+               FS_REF(native_internal_mount->mnt_fs);
+               *mntp = mnt;
+       }
+       return err;
+}
+
+static int
+native_i_invalid(struct inode *inop, struct intnl_stat stbuf)
+{
+       /*
+        * Validate passed in inode against stat struct info
+        */
+       struct native_inode *nino = I2NI(inop);
+       
+       if ((nino->ni_ident.dev != stbuf.st_dev ||
+            nino->ni_ident.ino != stbuf.st_ino ||
+#ifdef HAVE_GENERATION
+            nino->ni_ident.gen != stbuf.st_gen ||
+#endif
+            ((inop)->i_mode & S_IFMT) != (stbuf.st_mode & S_IFMT)) ||
+           (((inop)->i_rdev != stbuf.st_rdev) &&
+              (S_ISCHR((inop)->i_mode) || S_ISBLK((inop)->i_mode))))
+               return 1;
+       
+       return 0;
+}
+
+/*
+ * Find, and validate, or create i-node by host-relative path. Returned i-node
+ * is referenced.
+ */
+static int
+native_iget(struct filesys *fs,
+           const char *path,
+           struct inode **inop,
+           int forced)
+{
+       int     err;
+       struct inode *ino;
+       struct intnl_stat stbuf;
+       struct native_inode_identifier ident;
+       struct file_identifier fileid;
+
+       /*
+        * Get file status.
+        */
+       err = native_stat(path, &stbuf);
+       if (err) {
+               *inop = NULL;
+               return err;
+       }
+
+       /* 
+        * Validate?
+        */
+       if (*inop) {
+               if (!native_i_invalid(*inop, stbuf))
+                       return 0;
+               /*
+                * Invalidate.
+                */
+               *inop = NULL;
+       }
+
+       /*
+        * I-node is not already known. Find or create it.
+        */
+       bzero(&ident, sizeof(ident)); 
+       ident.dev = stbuf.st_dev;
+       ident.ino = stbuf.st_ino;
+#ifdef HAVE_GENERATION
+       ident.gen = stbuf.st_gen;
+#endif
+       fileid.fid_data = &ident;
+       fileid.fid_len = sizeof(ident);
+       ino = _sysio_i_find(fs, &fileid);
+       if (ino && forced) {
+               /*
+                * Insertion was forced but it's already present!
+                */
+               if (native_i_invalid(ino, stbuf)) {
+                       /* 
+                        * Cached inode has stale attrs
+                        * make way for the new one
+                        */
+                       I_GONE(ino);
+                       ino = NULL;
+               } else
+                       /* 
+                        * OK to reuse cached inode
+                        */
+                       goto out;
+       }
+
+       if (!ino) {
+               ino = native_i_new(fs, &stbuf);
+               if (!ino)
+                       err = -ENOMEM;
+       }
+out:
+       if (!err)
+               *inop = ino;
+       return err;
+}
+
+/*
+ * Look up named object in host's name space by path.
+ */
+static int
+native_path_lookup(struct filesys *fs, const char *path, struct inode **inop)
+{
+
+       return native_iget(fs, path, inop, 0);
+}
+
+/*
+ * Look up object by it's path node.
+ */
+static int
+native_i_lookup(struct filesys *fs, struct pnode_base *pb, struct inode **inop)
+{
+       int     err;
+       char    *path;
+
+       path = _sysio_pb_path(pb, '/');
+       if (!path)
+               return -ENOMEM;
+       err = native_path_lookup(fs, path, inop);
+       free(path);
+       return err;
+}
+
+static int
+native_inop_lookup(struct pnode *pno,
+                  struct inode **inop,
+                  struct intent *intnt __IS_UNUSED,
+                  const char *path __IS_UNUSED)
+{
+       int     err;
+
+       *inop = pno->p_base->pb_ino;
+
+       /*
+        * Don't have an inode yet. Because we translate everything back to
+        * a single name space for the host, we will assume the object the
+        * caller is looking for has no existing alias in our internal
+        * name space. We don't see the same file on different mounts in the
+        * underlying host FS as the same file.
+        *
+        * The file identifier *will* be unique. It's got to have a different
+        * dev.
+        */
+       err = native_i_lookup(pno->p_mount->mnt_fs, pno->p_base, inop);
+       if (err)
+               *inop = NULL;
+       return err;
+}
+
+static int
+native_inop_getattr(struct pnode *pno, struct inode *ino, struct intnl_stat *stbuf)
+{
+       char    *path;
+       int     err;
+
+       path = NULL;
+       if (!ino || I2NI(ino)->ni_fd < 0) {
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+       err =
+           path
+             ? native_stat(path, stbuf)
+             : native_fstat(I2NI(ino)->ni_fd, stbuf);
+       if (path)
+               free(path);
+       return err;
+}
+
+static int
+native_inop_setattr(struct pnode *pno,
+                   struct inode *ino,
+                   unsigned mask,
+                   struct intnl_stat *stbuf)
+{
+       char    *path;
+       int     fd;
+       struct intnl_stat st;
+       int     err;
+
+       path = NULL;
+       fd = ino ? I2NI(ino)->ni_fd : -1;
+       if (fd < 0 || mask & (SETATTR_MTIME|SETATTR_ATIME)) {
+               if (!pno)
+                       return -EEXIST;
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+
+       /*
+        * Get current status for undo.
+        */
+       err =
+           fd < 0
+             ? native_stat(path, &st)
+             : native_fstat(fd, &st);
+       if (err)
+               goto out;
+
+       if (mask & SETATTR_MODE) {
+               mode_t  mode;
+
+               /*
+                * Alter permissions attribute.
+                */
+               mode = stbuf->st_mode & 07777;
+               err =
+                   fd < 0
+                     ? syscall(SYS_chmod, path, mode)
+                     : syscall(SYS_fchmod, fd, mode);
+               if (err)
+                       err = -errno;
+       }
+       if (err)
+               mask &= ~SETATTR_MODE;
+       else if (mask & (SETATTR_MTIME|SETATTR_ATIME)) {
+               struct utimbuf ut;
+
+               /*
+                * Alter access and/or modify time attributes.
+                */
+               ut.actime = st.st_atime;
+               ut.modtime = st.st_mtime;
+               if (mask & SETATTR_MTIME)
+                       ut.modtime = stbuf->st_mtime;
+               if (mask & SETATTR_ATIME)
+                       ut.actime = stbuf->st_atime;
+               err = syscall(__SYS_UTIME, path, &ut);
+               if (err)
+                       err = -errno;
+       }
+       if (err)
+               mask &= ~(SETATTR_MTIME|SETATTR_ATIME);
+       else if (mask & (SETATTR_UID|SETATTR_GID)) {
+
+               /*
+                * Alter owner and/or group identifiers.
+                */
+               err =
+                   fd < 0
+                     ? syscall(SYS_chown,
+                               path,
+                               mask & SETATTR_UID
+                                 ? stbuf->st_uid
+                                 : (uid_t )-1,
+                               mask & SETATTR_GID
+                                 ? stbuf->st_gid
+                                 : (gid_t )-1)
+                     : syscall(SYS_fchown,
+                               fd,
+                               mask & SETATTR_UID
+                                 ? stbuf->st_uid
+                                 : (uid_t )-1,
+                               mask & SETATTR_GID
+                                 ? stbuf->st_gid
+                                 : (gid_t )-1);
+               if (err)
+                       err = -errno;
+       }
+       if (err)
+               mask &= ~(SETATTR_UID|SETATTR_GID);
+       else if (mask & SETATTR_LEN) {
+               /*
+                * Do the truncate last. It can't be undone.
+                */
+                (void )(fd < 0
+                          ? syscall(__SYS_TRUNCATE, path, stbuf->st_size)
+                          : syscall(__SYS_FTRUNCATE, fd, stbuf->st_size));
+       }
+       if (!err)
+               goto out;
+       /*
+        * Undo after error. Some or all of this might not work... We
+        * can but try.
+        */
+       if (mask & (SETATTR_UID|SETATTR_GID)) {
+                (void )(fd < 0
+                          ? syscall(SYS_chown,
+                                    path,
+                                    mask & SETATTR_UID
+                                      ? st.st_uid
+                                      : (uid_t )-1,
+                                    mask & SETATTR_GID
+                                      ? st.st_gid
+                                      : (gid_t )-1)
+                          : syscall(SYS_fchown,
+                                    fd,
+                                    mask & SETATTR_UID
+                                      ? st.st_uid
+                                      : (uid_t )-1,
+                                    mask & SETATTR_GID
+                                      ? st.st_gid
+                                      : (gid_t )-1));
+       }
+       if (mask & (SETATTR_MTIME|SETATTR_ATIME)) {
+               struct utimbuf ut;
+
+               ut.actime = st.st_atime;
+               ut.modtime = st.st_mtime;
+               (void )syscall(__SYS_UTIME, path, &ut);
+       }
+       if (mask & SETATTR_MODE) {
+               fd < 0
+                 ? syscall(SYS_chmod, path, st.st_mode & 07777)
+                 : syscall(SYS_fchmod, fd, st.st_mode & 07777);
+       }
+out:
+       if (path)
+               free(path);
+       return err;
+}
+
+static int
+native_pos(int fd, _SYSIO_OFF_T *offset, int whence)
+{
+       _SYSIO_OFF_T off;
+
+       assert(fd >= 0);
+       assert(*offset >= 0);
+
+       off = *offset;
+#if _LARGEFILE64_SOURCE && defined(SYS__llseek)
+       {
+               int     err;
+               err =
+                   syscall(SYS__llseek,
+                           (unsigned int)fd,
+                           (unsigned int)(off >> 32),
+                           (unsigned int)off,
+                           &off,
+                           whence);
+               if (err == -1)
+                       return -errno;
+       }
+#else
+       off =
+           syscall(SYS_lseek,
+                   fd,
+                   off,
+                   whence);
+       if (off == -1)
+               return -errno;
+#endif
+       *offset = off;
+
+       return 0;
+}
+
+static ssize_t
+native_filldirentries(struct native_inode *nino,
+                     char *buf,
+                     size_t nbytes,
+                     _SYSIO_OFF_T *basep)
+{
+       int     err;
+       ssize_t cc;
+
+       if (*basep < 0)
+               return -EINVAL;
+
+#if DIR_STREAMED
+       /*
+        * Stream-oriented access requires that we reposition prior to the
+        * fill call.
+        */
+       if ((err = native_pos(nino->ni_fd, basep, SEEK_SET)) != 0)
+               return err;
+#endif
+       nino->ni_fpos = *basep;
+
+       cc =
+#if defined(SYS_getdirentries)
+           syscall(SYS_getdirentries,
+                   nino->ni_fd,
+                   buf,
+                   nbytes,
+                   basep);
+#elif defined(SYS_getdents64)
+           syscall(SYS_getdents64, nino->ni_fd, buf, nbytes);
+#elif defined(SYS_getdents)
+           syscall(SYS_getdents, nino->ni_fd, buf, nbytes);
+#endif
+
+       if (cc < 0)
+               return -errno;
+#if DIR_STREAMED
+       /*
+        * Stream-oriented access requires that we discover where we are
+        * after the call.
+        */
+       *basep = 0;
+       if ((err = native_pos(nino->ni_fd, basep, SEEK_CUR)) != 0)
+               return err;
+#endif
+       nino->ni_fpos = *basep;
+       return cc;
+}
+
+static ssize_t
+native_getdirentries(struct inode *ino,
+                    char *buf,
+                    size_t nbytes,
+                    _SYSIO_OFF_T *basep)
+{
+       struct native_inode *nino = I2NI(ino);
+#if DIR_CVT_64
+       char    *bp;
+       size_t  count;
+       struct linux_dirent *ldp;
+       struct dirent64 *d64p;
+       size_t  namlen;
+       size_t  reclen;
+#else
+#define bp buf
+#define count nbytes
+#endif
+       ssize_t cc;
+
+       assert(nino->ni_fd >= 0);
+
+#if DIR_CVT_64
+       count = nbytes;
+       while (!(bp = malloc(count))) {
+               count /= 2;
+               if (count < sizeof(struct dirent))
+                       return -ENOMEM;
+       }
+#endif
+       cc = native_filldirentries(nino, bp, count, basep);
+       if (cc < 0) {
+#if DIR_CVT_64
+               free(bp);
+#endif
+               return cc;
+       }
+#if DIR_CVT_64
+       ldp = (struct linux_dirent *)bp;
+       d64p = (struct dirent64 *)buf;
+       for (;;) {
+               if (cc < 0 || (size_t )cc <= sizeof(*ldp))
+                       break;
+               namlen = strlen(ldp->ld_name);
+               reclen = sizeof(*d64p) - sizeof(d64p->d_name) + namlen + 1;
+               if (nbytes < reclen)
+                       break;
+               d64p->d_ino = ldp->ld_ino;
+               d64p->d_off = ldp->ld_off;
+               d64p->d_reclen = 
+                   (((reclen + sizeof(long) - 1)) / sizeof(long)) *
+                   sizeof(long);
+               if (nbytes < d64p->d_reclen)
+                       d64p->d_reclen = reclen;
+               d64p->d_type = DT_UNKNOWN;              /* you lose -- sorry. */
+               (void )strncpy(d64p->d_name, ldp->ld_name, namlen);
+               *(d64p->d_name + namlen) = '\0';
+               cc -= ldp->ld_reclen;
+               ldp = (struct linux_dirent *)((char *)ldp + ldp->ld_reclen);
+               nbytes -= d64p->d_reclen;
+               d64p = (struct dirent64 *)((char *)d64p + d64p->d_reclen);
+       }
+       free(bp);
+       if (d64p == (struct dirent64 *)buf && cc)
+               cc = -EINVAL;                           /* buf too small */
+       cc = (char *)d64p - buf;
+#else
+#undef bp
+#undef count
+#endif
+       return cc;
+}
+
+static int
+native_inop_mkdir(struct pnode *pno, mode_t mode)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = syscall(SYS_mkdir, path, mode);
+       if (err != 0)
+               err = -errno;
+       free(path);
+       return err;
+}
+
+static int
+native_inop_rmdir(struct pnode *pno)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = syscall(SYS_rmdir, path);
+       if (err != 0)
+               err = -errno;
+       free(path);
+       return err;
+}
+
+static int
+native_inop_symlink(struct pnode *pno, const char *data)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = syscall(SYS_symlink, data, path);
+       if (err != 0)
+               err = -errno;
+       free(path);
+       return err;
+}
+
+static int
+native_inop_readlink(struct pnode *pno, char *buf, size_t bufsiz)
+{
+       char    *path;
+       int     i;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+       i = syscall(SYS_readlink, path, buf, bufsiz);
+       if (i < 0)
+               i = -errno;
+       free(path);
+       return i;
+}
+
+static int 
+native_inop_open(struct pnode *pno, int flags, mode_t mode)
+{
+       struct native_inode *nino;
+       char    *path;
+       int     fd;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * Whether the file is already open, or not, makes no difference.
+        * Want to always give the host OS a chance to authorize in case
+        * something has changed underneath us.
+        */
+       if (flags & O_WRONLY) {
+               /*
+                * Promote write-only attempt to RW.
+                */
+               flags &= ~O_WRONLY;
+               flags |= O_RDWR;
+       }
+#ifdef O_LARGEFILE
+       flags |= O_LARGEFILE;
+#endif
+       fd = syscall(SYS_open, path, flags, mode);
+       if (!pno->p_base->pb_ino && fd >= 0) {
+               int     err;
+
+               /*
+                * Success but we need to return an i-node.
+                */
+               err =
+                   native_iget(pno->p_mount->mnt_fs,
+                               path,
+                               &pno->p_base->pb_ino,
+                               1);
+               if (err) {
+                       (void )syscall(SYS_close, fd);
+                       if (err == -EEXIST)
+                               abort();
+                       fd = err;
+               }
+       }
+       free(path);
+       if (fd < 0)
+               return -errno;
+
+       /*
+        * Remember this new open.
+        */
+       nino = I2NI(pno->p_base->pb_ino);
+       nino->ni_nopens++;
+       assert(nino->ni_nopens);
+
+       if (nino->ni_fd >= 0) {
+               if ((nino->ni_oflags & O_RDWR) ||
+                   (flags & (O_RDONLY|O_WRONLY|O_RDWR)) == O_RDONLY) {
+                       /*
+                        * Keep existing.
+                        */
+                       (void )syscall(SYS_close, fd);
+                       return 0;
+               }
+               (void )syscall(SYS_close, nino->ni_fd);
+       }
+       /*
+        * Invariant; First open. Must init.
+        */
+       nino->ni_fpos = 0;
+       nino->ni_fd = fd;
+       /*
+        * Need to know whether we can seek on this
+        * descriptor.
+        */
+       nino->ni_seekok =
+           native_pos(nino->ni_fd, &nino->ni_fpos, SEEK_CUR) != 0 ? 0 : 1;
+
+       return 0;
+}
+
+static int
+native_inop_close(struct inode *ino)
+{
+       struct native_inode *nino = I2NI(ino);
+       int     err;
+
+       if (nino->ni_fd < 0)
+               abort();
+
+       assert(nino->ni_nopens);
+       if (--nino->ni_nopens) {
+               /*
+                * Hmmm. We really don't need anything else. However, some
+                * filesystems try to implement a sync-on-close semantic.
+                * As this appears now, that is lost. Might want to change
+                * it somehow in the future?
+                */
+               return 0;
+       }
+
+       err = syscall(SYS_close, nino->ni_fd);
+       if (err)
+               return -errno;
+
+       nino->ni_fd = -1;
+       nino->ni_fpos = 0;
+       return 0;
+}
+
+static int
+native_inop_link(struct pnode *old, struct pnode *new)
+{
+       int     err;
+       char    *opath, *npath;
+
+       err = 0;
+
+       opath = _sysio_pb_path(old->p_base, '/');
+       npath = _sysio_pb_path(new->p_base, '/');
+       if (!(opath && npath)) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = syscall(SYS_link, opath, npath);
+       if (err != 0)
+               err = -errno;
+
+out:
+       if (opath)
+               free(opath);
+       if (npath)
+               free(npath);
+
+       return err;
+}
+
+static int
+native_inop_unlink(struct pnode *pno)
+{
+       char    *path;
+       int     err = 0;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * For this driver, unlink is easy with open files. Since the
+        * file remains open to the system, too, the descriptors are still
+        * valid.
+        *
+        * Other drivers will have some difficulty here as the entry in the
+        * file system name space must be removed without sacrificing access
+        * to the file itself. In NFS this is done with a mechanism referred
+        * to as a `silly delete'. The file is moved to a temporary name
+        * (usually .NFSXXXXXX, where the X's are replaced by the PID and some
+        * unique characters) in order to simulate the proper semantic.
+        */
+       if (syscall(SYS_unlink, path) != 0)
+               err = -errno;
+       free(path);
+       return err;
+}
+
+static int
+native_inop_rename(struct pnode *old, struct pnode *new)
+{
+       int     err;
+       char    *opath, *npath;
+
+       opath = _sysio_pb_path(old->p_base, '/');
+       npath = _sysio_pb_path(new->p_base, '/');
+       if (!(opath && npath)) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = syscall(SYS_rename, opath, npath);
+       if (err != 0)
+               err = -errno;
+
+out:
+       if (opath)
+               free(opath);
+       if (npath)
+               free(npath);
+
+       return err;
+}
+
+static ssize_t
+dopio(void *buf, size_t count, _SYSIO_OFF_T off, struct native_io *nio)
+{
+#if defined(_LARGEFILE64_SOURCE) && \
+    defined(SYS_pread64) && \
+    defined(SYS_pwrite64)
+#define _NATIVE_SYSCALL_PREAD SYS_pread64
+#define _NATIVE_SYSCALL_PWRITE SYS_pwrite64
+#else
+#define _NATIVE_SYSCALL_PREAD SYS_pread
+#define _NATIVE_SYSCALL_PWRITE SYS_pwrite
+#endif
+       ssize_t cc;
+
+       if (!(off == nio->nio_nino->ni_fpos || nio->nio_nino->ni_seekok))
+               return -ESPIPE;
+               
+       if (!nio->nio_nino->ni_seekok) {
+               if (off != nio->nio_nino->ni_fpos) {
+                       /*
+                        * They've done a p{read,write} or somesuch. Can't
+                        * seek on this descriptor so we err out now.
+                        */
+                       errno = ESPIPE;
+                       return -1;
+               }
+               cc =
+                   syscall(nio->nio_op == 'r' ? SYS_read : SYS_write,
+                           nio->nio_nino->ni_fd,
+                           buf,
+                           count);
+               if (cc > 0)
+                       nio->nio_nino->ni_fpos += cc;
+       } else
+               cc =
+                   syscall((nio->nio_op == 'r'
+                              ? _NATIVE_SYSCALL_PREAD
+                              : _NATIVE_SYSCALL_PWRITE),
+                           nio->nio_nino->ni_fd,
+                           buf,
+                           count,
+                           off);
+
+       return cc;
+#undef _NATIVE_SYSCALL_PREAD
+#undef _NATIVE_SYSCALL_PWRITE
+}
+
+static ssize_t
+doiov(const struct iovec *iov,
+      int count,
+      _SYSIO_OFF_T off,
+      ssize_t limit,
+      struct native_io *nio)
+{
+       ssize_t cc;
+
+#if !(defined(REDSTORM) || defined(MAX_IOVEC))
+#define MAX_IOVEC      INT_MAX
+#endif
+
+       if (count <= 0)
+               return -EINVAL;
+
+       /*
+        * Avoid the reposition call if we're already at the right place.
+        * Allows us to access pipes and fifos.
+        */
+       if (off != nio->nio_nino->ni_fpos) {
+               int     err;
+
+               err = native_pos(nio->nio_nino->ni_fd, &off, SEEK_SET);
+               if (err)
+                       return err;
+               nio->nio_nino->ni_fpos = off;
+       }
+
+       /*
+        * The {read,write}v is safe as this routine is only ever called
+        * by _sysio_enumerate_extents() and that routine is exact. It never
+        * passes iovectors including tails.
+        */
+       cc =
+#ifndef REDSTORM
+           count <= MAX_IOVEC
+             ? syscall(nio->nio_op == 'r' ? SYS_readv : SYS_writev,
+                       nio->nio_nino->ni_fd,
+                       iov,
+                       count)
+             :
+#endif
+               _sysio_enumerate_iovec(iov,
+                                      count,
+                                      off,
+                                      limit,
+                                      (ssize_t (*)(void *,
+                                                   size_t,
+                                                   _SYSIO_OFF_T,
+                                                   void *))dopio,
+                                      nio);
+       if (cc < 0)
+               cc = -errno;
+       else
+               nio->nio_nino->ni_fpos += cc;
+       return cc;
+
+#if !(defined(REDSTORM) || defined(MAX_IOVEC))
+#undef MAX_IOVEC
+#endif
+}
+
+#if 0
+static int
+lockop_all(struct native_inode *nino,
+          struct intnl_xtvec *xtv,
+          size_t count,
+          short op)
+{
+       struct flock flock;
+       int     err;
+
+       if (!count)
+               return -EINVAL;
+       flock.l_type = op;
+       flock.l_whence = SEEK_SET;
+       while (count--) {
+               flock.l_start = xtv->xtv_off;
+               flock.l_len = xtv->xtv_len;
+               xtv++;
+               err =
+                   syscall(
+#if !_LARGEFILE64_SOURCE
+                           SYS_fcntl64
+#else
+                           SYS_fcntl
+#endif
+                           ,
+                           nino->ni_fd,
+                           F_SETLK,
+                           &flock);
+               if (err != 0)
+                       return -errno;
+       }
+       return 0;
+}
+
+static int
+order_xtv(const struct intnl_xtvec *xtv1, const struct intnl_xtvec *xtv2)
+{
+
+       if (xtv1->xtv_off < xtv2->xtv_off)
+               return -1;
+       if (xtv1->xtv_off > xtv2->xtv_off)
+               return 1;
+       return 0;
+}
+#endif
+
+static int
+doio(char op, struct ioctx *ioctx)
+{
+       struct native_inode *nino;
+#if 0
+       int     dolocks;
+       struct intnl_xtvec *oxtv;
+       int     err;
+#endif
+       struct native_io arguments;
+       ssize_t cc;
+#if 0
+       struct intnl_xtvec *front, *rear, tmp;
+#endif
+
+       nino = I2NI(ioctx->ioctx_ino);
+#if 0
+       dolocks = ioctx->ioctx_xtvlen > 1 && nino->ni_seekok;
+       if (dolocks) {
+               /*
+                * Must lock the regions (in order!) since we can't do
+                * strided-IO as a single atomic operation.
+                */
+               oxtv = malloc(ioctx->ioctx_xtvlen * sizeof(struct intnl_xtvec));
+               if (!oxtv)
+                       return -ENOMEM;
+               (void )memcpy(oxtv,
+                             ioctx->ioctx_xtv, 
+                             ioctx->ioctx_xtvlen * sizeof(struct intnl_xtvec));
+               qsort(oxtv,
+                     ioctx->ioctx_xtvlen,
+                     sizeof(struct intnl_xtvec),
+                     (int (*)(const void *, const void *))order_xtv);
+               err =
+                   lockop_all(nino,
+                              oxtv, ioctx->ioctx_xtvlen,
+                              op == 'r' ? F_RDLCK : F_WRLCK);
+               if (err) {
+                       free(oxtv);
+                       return err;
+               }
+       }
+#endif
+       arguments.nio_op = op;
+       arguments.nio_nino = nino;
+       cc =
+           _sysio_enumerate_extents(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen, 
+                                    ioctx->ioctx_iov, ioctx->ioctx_iovlen,
+                                    (ssize_t (*)(const struct iovec *,
+                                                 int,
+                                                 _SYSIO_OFF_T,
+                                                 ssize_t,
+                                                 void *))doiov,
+                                    &arguments);
+#if 0
+       if (dolocks) {
+               /*
+                * Must unlock in reverse order.
+                */
+               front = oxtv;
+               rear = front + ioctx->ioctx_xtvlen - 1;
+               while (front < rear) {
+                       tmp = *front;
+                       *front++ = *rear;
+                       *rear-- = tmp;
+               }
+               if (lockop_all(nino, oxtv, ioctx->ioctx_xtvlen, F_UNLCK) != 0)
+                       abort();
+               free(oxtv);
+       }
+#endif
+       if ((ioctx->ioctx_cc = cc) < 0) {
+               ioctx->ioctx_errno = -ioctx->ioctx_cc;
+               ioctx->ioctx_cc = -1;
+       }
+       return 0;
+}
+
+static int
+native_inop_read(struct inode *ino __IS_UNUSED, struct ioctx *ioctx)
+{
+
+       return doio('r', ioctx);
+}
+
+static int
+native_inop_write(struct inode *ino __IS_UNUSED, struct ioctx *ioctx)
+{
+
+       return doio('w', ioctx);
+}
+
+static _SYSIO_OFF_T
+native_inop_pos(struct inode *ino, _SYSIO_OFF_T off)
+{
+       struct native_inode *nino = I2NI(ino);
+       int     err;
+
+       err = native_pos(nino->ni_fd, &off, SEEK_SET);
+       return err < 0 ? err : off;
+}
+
+static int
+native_inop_iodone(struct ioctx *ioctxp __IS_UNUSED)
+{
+
+       /*
+        * It's always done in this driver. It completed when posted.
+        */
+       return 1;
+}
+
+static int
+native_inop_fcntl(struct inode *ino,
+                 int cmd,
+                 va_list ap)
+{
+       struct native_inode *nino = I2NI(ino);
+       long    arg;
+       int     err;
+
+       if (nino->ni_fd < 0)
+               abort();
+
+       switch (cmd) {
+       case F_GETFD:
+       case F_GETFL:
+       case F_GETOWN:
+               err = syscall(SYS_fcntl, nino->ni_fd, cmd);
+               if (err < 0)
+                       err = -errno;
+       case F_DUPFD:
+       case F_SETFD:
+       case F_SETFL:
+       case F_GETLK:
+       case F_SETLK:
+       case F_SETLKW:
+       case F_SETOWN:
+               arg = va_arg(ap, long);
+               err = syscall(SYS_fcntl, nino->ni_fd, cmd, arg);
+               if (err)
+                       err = -errno;
+       default:
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static int
+native_inop_mknod(struct pnode *pno __IS_UNUSED,
+                 mode_t mode __IS_UNUSED,
+                 dev_t dev __IS_UNUSED)
+{
+
+       return -ENOSYS;
+}
+
+#ifdef _HAVE_STATVFS
+static int
+native_inop_statvfs(struct pnode *pno,
+                   struct inode *ino,
+                   struct intnl_statvfs *buf)
+{
+       char    *path;
+       int    rc;
+       struct statfs fs;
+
+       path = NULL;
+       if (!ino || I2NI(ino)->ni_fd < 0) {
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+
+       /*
+        * The syscall interface does not support SYS_fstatvfs.
+        * Should possibly return ENOSYS, but thought it
+        * better to use SYS_fstatfs and fill in as much of
+        * the statvfs structure as possible.  This allows
+        * for more of a test of the sysio user interface.
+        */
+       rc =
+           path
+             ? syscall(SYS_statfs, path, &fs)
+             : syscall(SYS_fstatfs, I2NI(ino)->ni_fd, &fs);
+       if (path)
+               free(path);
+       if (rc < 0)
+               return -errno;
+
+       buf->f_bsize = fs.f_bsize;  /* file system block size */
+       buf->f_frsize = fs.f_bsize; /* file system fundamental block size */
+       buf->f_blocks = fs.f_blocks;
+       buf->f_bfree = fs.f_bfree;
+       buf->f_bavail = fs.f_bavail;
+       buf->f_files = fs.f_files;  /* Total number serial numbers */
+       buf->f_ffree = fs.f_ffree;  /* Number free serial numbers */
+       buf->f_favail = fs.f_ffree; /* Number free ser num for non-privileged*/
+       buf->f_fsid = fs.f_fsid.__val[1];
+       buf->f_flag = 0;            /* No equiv in statfs; maybe use type? */
+       buf->f_namemax = fs.f_namelen;
+       return 0;
+}
+#endif
+
+static int
+native_inop_sync(struct inode *ino)
+{
+       int     err;
+
+       assert(I2NI(ino)->ni_fd >= 0);
+
+       err = syscall(SYS_fsync, I2NI(ino)->ni_fd);
+       if (err)
+               err = -errno;
+       return err;
+}
+
+static int
+native_inop_datasync(struct inode *ino)
+{
+       int     err;
+
+       assert(I2NI(ino)->ni_fd >= 0);
+
+#ifdef NATIVE_FDATASYNC
+       err = syscall(NATIVE_FDATASYNC, I2NI(ino)->ni_fd);
+#else
+#if 0
+#warning No fdatasync system call -- Using fsync instead!
+#endif
+       err = syscall(SYS_fsync, I2NI(ino)->ni_fd);
+#endif
+       if (err)
+               err = -errno;
+       return err;
+}
+
+static int
+native_inop_ioctl(struct inode *ino __IS_UNUSED,
+                 unsigned long int request __IS_UNUSED,
+                 va_list ap __IS_UNUSED)
+{
+
+       /*
+        * I'm lazy. Maybe implemented later.
+        */
+       errno = ENOTTY;
+       return -1;
+}
+
+static void
+native_inop_gone(struct inode *ino)
+{
+       struct native_inode *nino = I2NI(ino);
+
+       if (nino->ni_fd >= 0)
+               (void )syscall(SYS_close, nino->ni_fd);
+       free(ino->i_private);
+}
+
+static void
+native_fsop_gone(struct filesys *fs __IS_UNUSED)
+{
+
+       /*
+        * Do nothing. There is no private part maintained for the
+        * native file interface.
+        */
+}
diff --git a/libsysio/drivers/native/fs_native.h b/libsysio/drivers/native/fs_native.h
new file mode 100644 (file)
index 0000000..1590379
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Native file system driver support.
+ */
+
+extern int _sysio_native_init(void);
diff --git a/libsysio/drivers/native/module.mk b/libsysio/drivers/native/module.mk
new file mode 100644 (file)
index 0000000..8cada8a
--- /dev/null
@@ -0,0 +1,2 @@
+NATIVE_SRCS  = drivers/native/fs_native.c
+NATIVE_EXTRA = drivers/native/fs_native.h drivers/native/module.mk
diff --git a/libsysio/drivers/sockets/module.mk b/libsysio/drivers/sockets/module.mk
new file mode 100644 (file)
index 0000000..261fcfa
--- /dev/null
@@ -0,0 +1,2 @@
+SOCKETS_SRCS = drivers/sockets/sockets.c
+SOCKETS_EXTRA = drivers/sockets/module.mk
diff --git a/libsysio/drivers/sockets/sockets.c b/libsysio/drivers/sockets/sockets.c
new file mode 100644 (file)
index 0000000..b8da195
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#ifdef __linux__
+#define _BSD_SOURCE
+#endif
+
+#include <stdio.h>                                     /* for NULL */
+#include <stdlib.h>
+#ifdef __linux__
+#include <string.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/queue.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <linux/net.h>
+
+#include "sysio.h"
+#include "fs.h"
+#include "inode.h"
+#include "file.h"
+#include "dev.h"                                       /* _sysio_nodev_ops */
+
+/*
+ * Sockets interface driver
+ */
+
+/*
+ * Sockets file identifiers format.
+ */
+struct sockets_ino_identifier {
+       ino_t   inum;                                   /* i-number */
+};
+
+/*
+ * Driver-private i-node information we keep about in-use sockets.
+ */
+struct socket_info {
+       struct sockets_ino_identifier ski_ident;        /* unique identifier */
+       struct file_identifier ski_fileid;              /* ditto */
+       int     ski_fd;                         /* host fildes */
+};
+
+static int sockets_inop_close(struct inode *ino);
+static int sockets_inop_read(struct inode *ino,
+                            struct ioctx *ioctx);
+static int sockets_inop_write(struct inode *ino,
+                             struct ioctx *ioctxp);
+static _SYSIO_OFF_T sockets_inop_pos(struct inode *ino,
+                                    _SYSIO_OFF_T off);
+static int sockets_inop_iodone(struct ioctx *ioctx);
+static int sockets_inop_sync(struct inode *ino);
+static int sockets_inop_datasync(struct inode *ino);
+static int sockets_inop_fcntl(struct inode *ino, int cmd, va_list ap);
+static int sockets_inop_ioctl(struct inode *ino,
+                            unsigned long int request,
+                            va_list ap);
+static void sockets_inop_gone(struct inode *ino);
+static void sockets_illop(void);
+
+/*
+ * Given i-node, return driver private part.
+ */
+#define I2SKI(ino)     ((struct socket_info *)((ino)->i_private))
+
+struct filesys_ops sockets_filesys_ops = {
+       (void (*)(struct filesys *))sockets_illop
+};
+
+static struct filesys *sockets_fs;
+
+static struct inode_ops sockets_i_ops;
+
+/*
+ * Initialize this driver.
+ */
+int
+_sysio_sockets_init()
+{
+
+       sockets_i_ops = _sysio_nodev_ops;
+       sockets_i_ops.inop_close = sockets_inop_close;
+       sockets_i_ops.inop_read = sockets_inop_read;
+       sockets_i_ops.inop_write = sockets_inop_write;
+       sockets_i_ops.inop_pos = sockets_inop_pos;
+       sockets_i_ops.inop_iodone = sockets_inop_iodone;
+       sockets_i_ops.inop_fcntl = sockets_inop_fcntl;
+       sockets_i_ops.inop_sync = sockets_inop_sync;
+       sockets_i_ops.inop_datasync = sockets_inop_datasync;
+       sockets_i_ops.inop_ioctl = sockets_inop_ioctl;
+       sockets_i_ops.inop_gone = sockets_inop_gone;
+
+       sockets_fs = _sysio_fs_new(&sockets_filesys_ops, 0, NULL);
+       if (!sockets_fs)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int
+sockets_inop_close(struct inode *ino)
+{
+       struct socket_info *ski = I2SKI(ino);
+       int     err;
+
+       if (ski->ski_fd < 0)
+               return -EBADF;
+
+       err = syscall(SYS_close, ski->ski_fd);
+       if (err)
+               return -errno;
+       ski->ski_fd = -1;
+       return 0;
+}
+
+/*
+ * A helper function performing the real IO operation work.
+ *
+ * We don't really have async IO. We'll just perform the function
+ * now.
+ */
+static int
+doio(ssize_t (*f)(int, const struct iovec *, int),
+     struct inode *ino,
+     struct ioctx *ioctx)
+{
+       struct socket_info *ski = I2SKI(ino);
+
+       assert(ski->ski_fd >= 0);
+
+       /* XXX there's no way to check the position
+        * here we only could ingore the extends
+        */
+       if (ioctx->ioctx_xtvlen != 1)
+               return -EINVAL;
+
+       if (ioctx->ioctx_iovlen && (int) ioctx->ioctx_iovlen < 0)
+               return -EINVAL;
+
+       /*
+        * Call the appropriate (read/write) IO function to
+        * transfer the data now.
+        */
+       ioctx->ioctx_cc =
+           (*f)(ski->ski_fd, ioctx->ioctx_iov, ioctx->ioctx_iovlen);
+       if (ioctx->ioctx_cc < 0)
+               ioctx->ioctx_errno = errno;
+
+       ioctx->ioctx_done = 1;
+       return 0;
+}
+
+/*
+ * Helper function passed to doio(), above, to accomplish a real readv.
+ */
+static ssize_t
+_readv(int fd, const struct iovec *vector, int count)
+{
+
+       return syscall(SYS_readv, fd, vector, count);
+}
+
+static int
+sockets_inop_read(struct inode *ino,
+                 struct ioctx *ioctx)
+{
+
+       return doio(_readv, ino, ioctx);
+}
+
+/*
+ * Helper function passed to doio(), above, to accomplish a real writev.
+ */
+static ssize_t
+_writev(int fd, const struct iovec *vector, int count)
+{
+
+       return syscall(SYS_writev, fd, vector, count);
+}
+
+static int
+sockets_inop_write(struct inode *ino,
+                  struct ioctx *ioctx)
+{
+
+       return doio(_writev, ino, ioctx);
+}
+
+static _SYSIO_OFF_T
+sockets_inop_pos(struct inode *ino, _SYSIO_OFF_T off)
+{
+       return -EINVAL;
+}
+
+static int
+sockets_inop_iodone(struct ioctx *ioctxp __IS_UNUSED)
+{
+
+       /*
+        * It's always done in this driver. It completed when posted.
+        */
+       return 1;
+}
+
+static int
+sockets_inop_fcntl(struct inode *ino __IS_UNUSED,
+                 int cmd __IS_UNUSED,
+                 va_list ap __IS_UNUSED)
+{
+       long arg;
+
+       assert(I2SKI(ino)->ski_fd >= 0);
+
+       switch (cmd) {
+       case F_GETFD:
+       case F_GETFL:
+       case F_GETOWN:
+               return syscall(SYS_fcntl, I2SKI(ino)->ski_fd, cmd);
+       case F_DUPFD:
+       case F_SETFD:
+       case F_SETFL:
+       case F_GETLK:
+       case F_SETLK:
+       case F_SETLKW:
+       case F_SETOWN:
+               arg = va_arg(ap, long);
+               return syscall(SYS_fcntl, I2SKI(ino)->ski_fd, cmd, arg);
+       default:
+               printf("uncatched cmd %d\n", cmd);
+               abort();
+       }
+       return -1;
+}
+
+static int
+sockets_inop_sync(struct inode *ino)
+{
+
+       assert(I2SKI(ino)->ski_fd >= 0);
+
+       return syscall(SYS_fsync, I2SKI(ino)->ski_fd);
+}
+
+static int
+sockets_inop_datasync(struct inode *ino)
+{
+
+       assert(I2SKI(ino)->ski_fd >= 0);
+
+       return syscall(SYS_fdatasync, I2SKI(ino)->ski_fd);
+}
+
+static int
+sockets_inop_ioctl(struct inode *ino __IS_UNUSED,
+                 unsigned long int request __IS_UNUSED,
+                 va_list ap __IS_UNUSED)
+{
+       /*
+        * I'm lazy. Maybe implemented later.
+        */
+       return -ENOTTY;
+}
+
+static void
+sockets_inop_gone(struct inode *ino)
+{
+
+       (void )sockets_inop_close(ino);
+       free(ino->i_private);
+}
+
+static void
+sockets_illop(void)
+{
+
+       abort();
+}
+
+static struct inode *
+_sysio_sockets_inew()
+{
+       static ino_t inum = 1;
+       struct socket_info *ski;
+       struct inode *ino;
+
+       ski = malloc(sizeof(struct socket_info));
+       if (!ski)
+               return NULL;
+       ski->ski_ident.inum = inum++;
+       ski->ski_fileid.fid_data = &ski->ski_ident;
+       ski->ski_fileid.fid_len = sizeof(ski->ski_ident);
+       ski->ski_fd = -1;
+
+       ino =
+           _sysio_i_new(sockets_fs,
+                        &ski->ski_fileid,
+                        0,
+                        0,
+                        0,
+                        &sockets_i_ops,
+                        ski);
+       if (!ino)
+               free(ski);
+
+       return ino;
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+       int     err;
+       struct inode *ino;
+       struct socket_info *ski;
+       struct file *fil;
+
+       err = 0;
+       fil = NULL;
+
+       ino = _sysio_sockets_inew();
+       if (!ino) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       ski = I2SKI(ino);
+#ifndef SYS_socketcall
+       ski->ski_fd = syscall(SYS_socket, domain, type, protocol);
+#else
+       {
+               unsigned long avec[3] = {domain, type, protocol};
+               ski->ski_fd = syscall(SYS_socketcall, SYS_SOCKET, avec);
+       }
+#endif
+       if (ski->ski_fd < 0) {
+               err = -errno;
+               goto error;
+       }
+
+       fil = _sysio_fnew(ino, O_RDWR);
+       if (!fil) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       err = _sysio_fd_set(fil, ski->ski_fd);
+       if (err < 0)
+               goto error;
+
+       return err;
+
+error:
+       if (fil)
+               F_RELE(fil);
+       if (ino)
+               I_RELE(ino);
+
+       errno = -err;
+       return -1;
+}
+
+int
+accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+       int     err;
+       struct inode *ino;
+       struct socket_info *ski;
+       struct file *ofil, *nfil;
+
+       err = 0;
+       nfil = NULL;
+       ino = NULL;
+
+       ofil = _sysio_fd_find(s);
+       if (!ofil) {
+               err = -EBADF;
+               goto error;
+       }
+
+       ino = _sysio_sockets_inew();
+       if (!ino) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       nfil = _sysio_fnew(ino, O_RDWR);
+       if (!nfil) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       ski = I2SKI(ino);
+#ifndef SYS_socketcall
+       ski->ski_fd = syscall(SYS_accept, I2SKI(ofil->f_ino)->ski_fd,
+                               addr, addrlen);
+#else
+       {
+               unsigned long avec[3] = {
+                       (unsigned long) I2SKI(ofil->f_ino)->ski_fd,
+                       (unsigned long) addr,
+                       (unsigned long) addrlen};
+               ski->ski_fd = syscall(SYS_socketcall, SYS_ACCEPT, avec);
+       }
+#endif
+       if (ski->ski_fd < 0) {
+               err = -errno;
+               goto error;
+       }
+
+       err = _sysio_fd_set(nfil, ski->ski_fd);
+       if (err < 0)
+               goto error;
+
+       return err;
+
+error:
+       if (nfil)
+               F_RELE(nfil);
+       if (ino)
+               I_RELE(ino);
+
+       errno = -err;
+       return -1;
+}
+
+int
+bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
+{
+       int     err;
+       struct file *fil;
+       unsigned long avec[3];
+
+       err = 0;
+
+       fil = _sysio_fd_find(sockfd);
+       if (!fil) {
+               err = -EBADF;
+               goto out;
+       }
+
+#ifndef SYS_socketcall
+       if (syscall(SYS_bind, I2SKI(fil->f_ino)->ski_fd, my_addr, addrlen)) {
+#else
+       avec[0] = I2SKI(fil->f_ino)->ski_fd;
+       avec[1] = (unsigned long )my_addr;
+       avec[2] = addrlen;
+       if (syscall(SYS_socketcall, SYS_BIND, avec) != 0) {
+#endif
+               err = -errno;
+               goto out;
+       }
+
+       return 0;
+out:
+       errno = -err;
+       return -1;
+}
+
+int
+listen(int s, int backlog)
+{
+       int     err;
+       struct file *fil;
+       unsigned long avec[2];
+
+       err = 0;
+
+       fil = _sysio_fd_find(s);
+       if (!fil) {
+               err = -EBADF;
+               goto out;
+       }
+
+#ifndef SYS_socketcall
+       if (syscall(SYS_listen, I2SKI(fil->f_ino)->ski_fd, backlog) != 0) {
+#else
+       avec[0] = I2SKI(fil->f_ino)->ski_fd;
+       avec[1] = backlog;
+       if (syscall(SYS_socketcall, SYS_LISTEN, avec) != 0) {
+#endif
+               err = -errno;
+               goto out;
+       }
+
+       return 0;
+out:
+       errno = -err;
+       return -1;
+}
+
+int
+connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+       int     err;
+       struct file *fil;
+       unsigned long avec[3];
+
+       err = 0;
+
+       fil = _sysio_fd_find(sockfd);
+       if (!fil) {
+               err = -EBADF;
+               goto out;
+       }
+
+#ifndef SYS_socketcall
+       if (syscall(SYS_connect, I2SKI(fil->f_ino)->ski_fd,
+                   serv_addr, addrlen) != 0) {
+#else
+       avec[0] = I2SKI(fil->f_ino)->ski_fd;
+       avec[1] = (unsigned long )serv_addr;
+       avec[2] = addrlen;
+       if (syscall(SYS_socketcall, SYS_CONNECT, avec) != 0) {
+#endif
+               err = -errno;
+               goto out;
+       }
+
+       return 0;
+out:
+       errno = -err;
+       return -1;
+}
diff --git a/libsysio/drivers/yod/fs_yod.c b/libsysio/drivers/yod/fs_yod.c
new file mode 100644 (file)
index 0000000..d651b88
--- /dev/null
@@ -0,0 +1,1224 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#ifdef __linux__
+#define _BSD_SOURCE
+#endif
+
+#include <stdio.h>                                     /* for NULL */
+#include <stdlib.h>
+#ifdef __linux__
+#include <string.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#if 0
+#include <sys/vfs.h>
+#endif
+#ifdef _HAVE_STATVFS
+#include <sys/statvfs.h>
+#endif
+#include <utime.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+
+#include "sysio.h"
+#include "fs.h"
+#include "mount.h"
+#include "inode.h"
+
+#include "fs_yod.h"
+
+/*
+ * Remote file system driver
+ * calls are re-directed to the initiating yod
+ */
+#include "cplant-yod.h"
+
+/* stat struct used by yod, which
+ * is not compiled with __USE_FILE_OFFSET64
+ */
+#define __yod_stat stat
+#ifdef ALPHA_LINUX
+#define COPY_STAT(src, dest)                    \
+do {                                            \
+       memset((dest), 0, sizeof((*dest)));     \
+       (dest)->st_dev     = (src)->st_dev;     \
+       (dest)->st_ino     = (src)->st_ino;     \
+       (dest)->st_mode    = (src)->st_mode;    \
+       (dest)->st_nlink   = (src)->st_nlink;   \
+       (dest)->st_uid     = (src)->st_uid;     \
+       (dest)->st_gid     = (src)->st_gid;     \
+       (dest)->st_rdev    = (src)->st_rdev;    \
+       (dest)->st_size    = (src)->st_size;    \
+       (dest)->st_atime   = (src)->st_atime;   \
+       (dest)->st_mtime   = (src)->st_mtime;   \
+       (dest)->st_ctime   = (src)->st_ctime;   \
+       (dest)->st_blksize = (src)->st_blksize; \
+       (dest)->st_blocks  = (src)->st_blocks;  \
+       (dest)->st_flags   = (src)->st_flags;   \
+       (dest)->st_gen     = (src)->st_gen;     \
+} while (0);
+#else
+#define COPY_STAT(src, dest)                    \
+do {                                            \
+       memset((dest), 0, sizeof((*dest)));     \
+       (dest)->st_dev     = (src)->st_dev;     \
+       (dest)->st_ino     = (src)->st_ino;     \
+       (dest)->st_mode    = (src)->st_mode;    \
+       (dest)->st_nlink   = (src)->st_nlink;   \
+       (dest)->st_uid     = (src)->st_uid;     \
+       (dest)->st_gid     = (src)->st_gid;     \
+       (dest)->st_rdev    = (src)->st_rdev;    \
+       (dest)->st_size    = (src)->st_size;    \
+       (dest)->st_atime   = (src)->st_atime;   \
+       (dest)->st_mtime   = (src)->st_mtime;   \
+       (dest)->st_ctime   = (src)->st_ctime;   \
+       (dest)->st_blksize = (src)->st_blksize; \
+       (dest)->st_blocks  = (src)->st_blocks;  \
+} while (0);
+#endif
+
+/*
+ * Yod file identifiers format.
+ */
+struct yod_inode_identifier {
+       dev_t   dev;                                    /* device number */
+       ino_t   ino;                                    /* i-number */
+#ifdef HAVE_GENERATION
+       unsigned int gen;                               /* generation number */
+#endif
+};
+
+/*
+ * Driver-private i-node information we keep about local host file
+ * system objects.
+ */
+struct yod_inode {
+       unsigned ni_seekok              : 1;            /* can seek? */
+       struct yod_inode_identifier ni_ident;           /* unique identifier */
+       struct file_identifier ni_fileid;               /* ditto */
+       int     ni_fd;                                  /* host fildes */
+       int     ni_oflags;                              /* flags, from open */
+       unsigned ni_nopens;                             /* soft ref count */
+       _SYSIO_OFF_T ni_fpos;                           /* current pos */
+};
+
+static int yod_inop_lookup(struct pnode *pno,
+                             struct inode **inop,
+                             struct intent *intnt,
+                             const char *path);
+static int yod_inop_getattr(struct pnode *pno,
+                              struct inode *ino,
+                              struct intnl_stat *stbuf);
+static int yod_inop_setattr(struct pnode *pno,
+                              struct inode *ino,
+                              unsigned mask,
+                              struct intnl_stat *stbuf);
+static ssize_t yod_getdirentries(struct inode *ino,
+                                   char *buf,
+                                   size_t nbytes,
+                                   off64_t *basep);
+static int yod_inop_mkdir(struct pnode *pno, mode_t mode);
+static int yod_inop_rmdir(struct pnode *pno);
+static int yod_inop_symlink(struct pnode *pno, const char *data);
+static int yod_inop_readlink(struct pnode *pno, char *buf, size_t bufsiz);
+static int yod_inop_open(struct pnode *pno, int flags, mode_t mode);
+static int yod_inop_close(struct inode *ino);
+static int yod_inop_link(struct pnode *old, struct pnode *new);
+static int yod_inop_unlink(struct pnode *pno);
+static int yod_inop_rename(struct pnode *old, struct pnode *new);
+static _SYSIO_OFF_T yod_inop_pos (struct inode *ino, _SYSIO_OFF_T off);  
+static int yod_inop_read(struct inode *ino, struct ioctx *ioctx);
+static int yod_inop_write(struct inode *ino, struct ioctx *ioctx);
+static int yod_inop_iodone(struct ioctx *ioctx);
+static int yod_inop_fcntl(struct inode *ino, int cmd, va_list ap);
+static int yod_inop_sync(struct inode *ino);
+static int yod_inop_datasync(struct inode *ino);
+static int yod_inop_ioctl(struct inode *ino,
+                            unsigned long int request,
+                            va_list ap);
+static int yod_inop_mknod(struct pnode *pno, mode_t mode, dev_t dev);
+#ifdef _HAVE_STATVFS
+static int yod_inop_statvfs(struct pnode *pno,
+                              struct inode *ino,
+                              struct intnl_statvfs *buf);
+#endif
+static void yod_inop_gone(struct inode *ino);
+
+static struct inode_ops yod_i_ops = {
+       yod_inop_lookup,
+       yod_inop_getattr,
+       yod_inop_setattr,
+       yod_getdirentries,
+       yod_inop_mkdir,
+       yod_inop_rmdir,
+       yod_inop_symlink,
+       yod_inop_readlink,
+       yod_inop_open,
+       yod_inop_close,
+       yod_inop_link,
+       yod_inop_unlink,
+       yod_inop_rename,
+       yod_inop_read,
+       yod_inop_write,
+       yod_inop_pos,
+       yod_inop_iodone,
+       yod_inop_fcntl,
+       yod_inop_sync,
+       yod_inop_datasync,
+       yod_inop_ioctl,
+       yod_inop_mknod,
+#ifdef _HAVE_STATVFS
+       yod_inop_statvfs,
+#endif
+       yod_inop_gone
+};
+
+static int yod_fsswop_mount(const char *source,
+                              unsigned flags,
+                              const void *data,
+                              struct pnode *tocover,
+                              struct mount **mntp);
+
+static struct fssw_ops yod_fssw_ops = {
+       yod_fsswop_mount
+};
+
+static void yod_fsop_gone(struct filesys *fs);
+
+static struct filesys_ops yod_inodesys_ops = {
+       yod_fsop_gone
+};
+
+/* 
+ * Placeholder internal mount as in native driver
+ */
+static struct mount *yod_internal_mount = NULL;
+
+/*
+ * Given i-node, return driver private part.
+ */
+#define I2NI(ino)      ((struct yod_inode *)((ino)->i_private))
+
+/*
+ * stat -- by path.
+ */
+static int
+yod_stat(const char *path, struct intnl_stat *buf)
+{
+       int     err;
+       struct __yod_stat stbuf;
+       
+       err = stat_yod(path, &stbuf); 
+       if (err)
+               err = -errno;
+       COPY_STAT(&stbuf, buf);
+
+       return err;
+}
+
+/*
+ * stat -- by fildes
+ */
+static int
+yod_fstat(int fd, struct intnl_stat *buf)
+{
+       int     err;
+       struct __yod_stat stbuf;
+
+       err = fstat_yod(fd, &stbuf);
+       if (err)
+               err = -errno;
+       COPY_STAT(&stbuf, buf);
+
+       return err;
+}
+
+/*
+ * Introduce an i-node to the system.
+ */
+static struct inode *
+yod_i_new(struct filesys *fs, struct intnl_stat *buf)
+{
+       struct yod_inode *nino;
+       struct inode *ino;
+
+       nino = malloc(sizeof(struct yod_inode));
+       if (!nino)
+               return NULL;
+       bzero(&nino->ni_ident, sizeof(nino->ni_ident));
+       nino->ni_ident.dev = buf->st_dev;
+       nino->ni_ident.ino = buf->st_ino;
+#ifdef HAVE_GENERATION
+       nino->ni_ident.gen = buf->st_gen;
+#endif
+       nino->ni_fileid.fid_data = &nino->ni_ident;
+       nino->ni_fileid.fid_len = sizeof(nino->ni_ident);
+       nino->ni_fd = -1;
+       nino->ni_oflags = 0;
+       nino->ni_nopens = 0;
+       nino->ni_fpos = 0;
+       ino =
+           _sysio_i_new(fs,
+                        &nino->ni_fileid,
+#ifndef AUTOMOUNT_FILE_NAME
+                        buf->st_mode & S_IFMT,
+#else
+                        buf->st_mode,                  /* all of the bits! */
+#endif
+                        0,
+                        0,
+                        &yod_i_ops,
+                        nino);
+       if (!ino)
+               free(nino);
+       return ino;
+}
+
+/*
+ * Initialize this driver.
+ */
+int
+_sysio_yod_init()
+{
+
+       /*
+        * Capture current process umask and reset our process umask to
+        * zero. All permission bits to open/creat/setattr are absolute --
+        * They've already had a umask applied, when appropriate.
+        */
+       _sysio_umask = syscall(SYS_umask, 0);
+
+       return _sysio_fssw_register("yod", &yod_fssw_ops);
+}
+
+/*
+ * Create private, internal, view of the hosts name space.
+ */
+static int
+create_internal_namespace()
+{
+       int     err;
+       struct mount *mnt;
+       struct inode *rootino;
+       struct pnode_base *rootpb;
+       static struct qstr noname = { NULL, 0, 0 };
+       struct filesys *fs;
+       struct intnl_stat stbuf;
+
+       if (yod_internal_mount) {
+               /*
+                * Reentered!
+                */
+               abort();
+       }
+
+       /*
+        * We maintain an artificial, internal, name space in order to
+        * have access to fully qualified path names in the various routines.
+        * Initialize that name space now.
+        */
+       mnt = NULL;
+       rootino = NULL;
+       rootpb = NULL;
+       fs = _sysio_fs_new(&yod_inodesys_ops, 0, NULL);
+       if (!fs) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Get root i-node.
+        */
+       err = yod_stat("/", &stbuf);
+       if (err)
+               goto error;
+       rootino = yod_i_new(fs, &stbuf);
+       if (!rootino) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Generate base path-node for root.
+        */
+       rootpb = _sysio_pb_new(&noname, NULL, rootino);
+       if (!rootpb) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       /*
+        * Mount it. This name space is disconnected from the
+        * rest of the system -- Only available within this driver.
+        */
+       err = _sysio_do_mount(fs, rootpb, 0, NULL, &mnt);
+       if (err)
+               goto error;
+
+       yod_internal_mount = mnt;
+       return 0;
+error:
+       if (mnt) {
+               if (_sysio_do_unmount(mnt) != 0)
+                       abort();
+               fs = NULL;
+               rootpb = NULL;
+               rootino = NULL;
+       }
+       if (rootpb)
+               _sysio_pb_gone(rootpb);
+       if (fs) {
+               FS_RELE(fs);
+               _sysio_fs_gone(fs);
+       }
+
+       return err;
+}
+
+static int
+yod_fsswop_mount(const char *source,
+                unsigned flags,
+                const void *data __IS_UNUSED,
+                struct pnode *tocover,
+                struct mount **mntp)
+{
+       int     err;
+       struct nameidata nameidata;
+       struct mount *mnt;
+
+       /*
+        * Caller must use fully qualified path names when specifying
+        * the source.
+        */
+       if (*source != '/')
+               return -ENOENT;
+
+       if (!yod_internal_mount) {
+               err = create_internal_namespace();
+               if (err)
+                       return err;
+       }
+
+       /*
+        * Lookup the source in the internally maintained name space.
+        */
+       ND_INIT(&nameidata, 0, source, yod_internal_mount->mnt_root, NULL);
+       err = _sysio_path_walk(yod_internal_mount->mnt_root, &nameidata);
+       if (err)
+               return err;
+
+       /*
+        * Have path-node specified by the given source argument. Let the
+        * system finish the job, now.
+        */
+       err =
+           _sysio_do_mount(yod_internal_mount->mnt_fs,
+                           nameidata.nd_pno->p_base,
+                           flags,
+                           tocover,
+                           &mnt);
+       /*
+        * Release the internal name space pnode and clean up any
+        * aliases we might have generated. We really don't need to cache them
+        * as they are only used at mount time..
+        */
+       P_RELE(nameidata.nd_pno);
+       (void )_sysio_p_prune(yod_internal_mount->mnt_root);
+
+       if (!err) {
+               FS_REF(yod_internal_mount->mnt_fs);
+               *mntp = mnt;
+       }
+       return err;
+}
+
+static int
+yod_i_invalid(struct inode *inop, struct intnl_stat stbuf)
+{
+       /*
+        * Validate passed in inode against stat struct info
+        */
+       struct yod_inode *nino = I2NI(inop);
+       
+       if ((nino->ni_ident.dev != stbuf.st_dev ||
+            nino->ni_ident.ino != stbuf.st_ino ||
+#ifdef HAVE_GENERATION
+            nino->ni_ident.gen != stbuf.st_gen ||
+#endif
+            ((inop)->i_mode & S_IFMT) != (stbuf.st_mode & S_IFMT)) ||
+           (((inop)->i_rdev != stbuf.st_rdev) &&
+              (S_ISCHR((inop)->i_mode) || S_ISBLK((inop)->i_mode))))
+               return 1;
+       
+       return 0;
+}
+
+/*
+ * Find, and validate, or create i-node by host-relative path. Returned i-node
+ * is referenced.
+ */
+static int
+yod_iget(struct filesys *fs,
+           const char *path,
+           struct inode **inop,
+           int forced)
+{
+       int     err;
+       struct inode *ino;
+       struct intnl_stat stbuf;
+       struct yod_inode_identifier ident;
+       struct file_identifier fileid;
+
+       /*
+        * Get file status.
+        */
+       err = yod_stat(path, &stbuf);
+       if (err) {
+               *inop = NULL;
+               return err;
+       }
+
+       /*
+        * Validate?
+        */
+       if (*inop) {
+               if (!yod_i_invalid(*inop, stbuf))
+                       return 0;
+               /*
+                * Invalidate.
+                */
+               *inop = NULL;
+       }
+
+       /*
+        * I-node is not already known. Find or create it.
+        */
+       bzero(&ident, sizeof(ident)); 
+       ident.dev = stbuf.st_dev;
+       ident.ino = stbuf.st_ino;
+#ifdef HAVE_GENERATION
+       ident.gen = stbuf.st_gen;
+#endif
+       fileid.fid_data = &ident;
+       fileid.fid_len = sizeof(ident);
+       ino = _sysio_i_find(fs, &fileid);
+       if (ino && forced) {
+               /*
+                * Insertion was forced but it's already present!
+                */
+               if (yod_i_invalid(ino, stbuf)) {
+                       /* 
+                        * Cached inode has stale attrs
+                        * make way for the new one
+                        */
+                       I_RELE(ino);
+                       _sysio_i_undead(ino);
+                       ino = NULL;
+               } else
+                       /* 
+                        * OK to reuse cached inode
+                        */
+                       goto out;
+       }
+
+       if (!ino) {
+               ino = yod_i_new(fs, &stbuf);
+               if (!ino)
+                       err = -ENOMEM;
+       }
+out:
+       if (!err)
+               *inop = ino;
+       return err;
+}
+
+/*
+ * Look up named object in host's name space by path.
+ */
+static int
+yod_path_lookup(struct filesys *fs, const char *path, struct inode **inop)
+{
+
+       return yod_iget(fs, path, inop, 0);
+}
+
+/*
+ * Look up object by it's path node.
+ */
+static int
+yod_i_lookup(struct filesys *fs, struct pnode_base *pb, struct inode **inop)
+{
+       int     err;
+       char    *path;
+
+       path = _sysio_pb_path(pb, '/');
+       if (!path)
+               return -ENOMEM;
+       err = yod_path_lookup(fs, path, inop);
+       free(path);
+       return err;
+}
+
+static int
+yod_inop_lookup(struct pnode *pno,
+                  struct inode **inop,
+                  struct intent *intnt __IS_UNUSED,
+                  const char *path __IS_UNUSED)
+{
+       int     err;
+
+       *inop = pno->p_base->pb_ino;
+
+       /*
+        * Don't have an inode yet. Because we translate everything back to
+        * a single name space for the host, we will assume the object the
+        * caller is looking for has no existing alias in our internal
+        * name space. We don't see the same file on different mounts in the
+        * underlying host FS as the same file.
+        *
+        * The file identifier *will* be unique. It's got to have a different
+        * dev.
+        */
+       err = yod_i_lookup(pno->p_mount->mnt_fs, pno->p_base, inop);
+       if (err)
+               *inop = NULL;
+       return err;
+}
+
+static int
+yod_inop_getattr(struct pnode *pno, struct inode *ino, struct intnl_stat *stbuf)
+{
+       char    *path;
+       int     err;
+
+       path = NULL;
+       if (!ino || I2NI(ino)->ni_fd < 0) {
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+       err =
+           path
+             ? yod_stat(path, stbuf)
+             : yod_fstat(I2NI(ino)->ni_fd, stbuf);
+       if (path)
+               free(path);
+       return err;
+}
+
+static int
+yod_inop_setattr(struct pnode *pno,
+                   struct inode *ino,
+                   unsigned mask,
+                   struct intnl_stat *stbuf)
+{
+       char    *path;
+       int     fd;
+       struct intnl_stat st;
+       int     err;
+
+       path = NULL;
+       fd = ino ? I2NI(ino)->ni_fd : -1;
+       if (fd < 0 || mask & (SETATTR_MTIME|SETATTR_ATIME)) {
+               if (!pno)
+                       return -EEXIST;
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+
+       /*
+        * Get current status for undo.
+        */
+       err =
+           fd < 0
+             ? yod_stat(path, &st)
+             : yod_fstat(fd, &st);
+       if (err)
+               goto out;
+
+       if (mask & SETATTR_MODE) {
+               mode_t  mode;
+
+               /*
+                * Alter permissions attribute.
+                */
+               mode = stbuf->st_mode & 07777;
+               err = chmod_yod(path, mode);
+       }
+       if (err)
+               mask &= ~SETATTR_MODE;
+
+       if (mask & (SETATTR_UID|SETATTR_GID)) {
+
+               /*
+                * Alter owner and/or group identifiers.
+                */
+               err = chown_yod(path,
+                               mask & SETATTR_UID
+                                 ? stbuf->st_uid
+                                 : (uid_t )-1,
+                               mask & SETATTR_GID
+                                 ? stbuf->st_gid
+                                 : (gid_t )-1);
+       }
+       if (err)
+               mask &= ~(SETATTR_UID|SETATTR_GID);
+       else if (mask & SETATTR_LEN) {
+               /*
+                * Do the truncate last. It can't be undone.
+                */
+                (void )(fd < 0
+                          ? truncate_yod(path, stbuf->st_size)
+                          : ftruncate_yod(fd, stbuf->st_size));
+       }
+       if (!err)
+               goto out;
+       /*
+        * Undo after error. Some or all of this might not work... We
+        * can but try.
+        */
+       if (mask & (SETATTR_UID|SETATTR_GID)) {
+                (void )chown_yod(path,
+                                 mask & SETATTR_UID
+                                   ? st.st_uid
+                                   : (uid_t )-1,
+                                 mask & SETATTR_GID
+                                   ? st.st_gid
+                                   : (gid_t )-1);
+       }
+       if (mask & SETATTR_MODE) {
+               chmod_yod(path, st.st_mode & 07777);
+       }
+out:
+       if (path)
+               free(path);
+       return err;
+}
+
+static ssize_t
+yod_getdirentries(struct inode *ino,
+                    char *buf,
+                    size_t nbytes,
+                    off64_t *basep)
+{
+       struct yod_inode *nino = I2NI(ino);
+       loff_t  result;
+       ssize_t cc;
+
+       assert(nino->ni_fd >= 0);
+
+       result = *basep;
+       if (*basep != nino->ni_fpos &&
+           (result = lseek_yod(nino->ni_fd,
+                               *basep,
+                               SEEK_SET) == -1))
+               return -errno;
+       nino->ni_fpos = result;
+       cc = getdirentries_yod(nino->ni_fd, buf, nbytes, &result);
+       if (cc < 0)
+               return -errno;
+       nino->ni_fpos += cc;
+       return cc;
+}
+
+static int
+yod_inop_mkdir(struct pnode *pno, mode_t mode)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = mkdir_yod(path, mode);
+       free(path);
+       return err;
+}
+
+static int
+yod_inop_rmdir(struct pnode *pno)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = rmdir_yod(path);
+       free(path);
+       return err;
+}
+
+static int
+yod_inop_symlink(struct pnode *pno, const char *data)
+{
+       char    *path;
+       int     err;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       err = symlink_yod(data, path);
+       free(path);
+       return err;
+}
+
+static int
+yod_inop_readlink(struct pnode *pno __IS_UNUSED, 
+                 char *buf __IS_UNUSED, 
+                 size_t bufsiz __IS_UNUSED)
+{
+
+       return -ENOSYS;
+}
+
+static int
+yod_inop_open(struct pnode *pno, int flags, mode_t mode)
+{
+       struct yod_inode *nino;
+       char    *path;
+       int     fd;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * Whether the file is already open, or not, makes no difference.
+        * Want to always give the host OS a chance to authorize in case
+        * something has changed underneath us.
+        */
+       if (flags & O_WRONLY) {
+               /*
+                * Promote write-only attempt to RW.
+                */
+               flags &= ~O_WRONLY;
+               flags |= O_RDWR;
+       }
+       fd = open_yod(path, flags, mode);
+       if (!pno->p_base->pb_ino && fd >= 0) {
+               int     err;
+
+               /*
+                * Success but we need to return an i-node.
+                */
+               err =
+                   yod_iget(pno->p_mount->mnt_fs,
+                               path,
+                               &pno->p_base->pb_ino,
+                               1);
+               if (err) {
+                       (void )close_yod(fd);
+                       if (err == -EEXIST)
+                               abort();
+                       fd = err;
+               }
+       }
+       free(path);
+       if (fd < 0)
+               return -errno;
+
+       /*
+        * Remember this new open.
+        */
+       nino = I2NI(pno->p_base->pb_ino);
+       nino->ni_nopens++;
+       assert(nino->ni_nopens);
+
+       if (nino->ni_fd >= 0) {
+               if ((nino->ni_oflags & O_RDWR) ||
+                   (flags & (O_RDONLY|O_WRONLY|O_RDWR)) == O_RDONLY) {
+                       /*
+                        * Keep existing.
+                        */
+                       (void )close_yod(fd);
+                       return 0;
+               }
+               (void )close_yod(nino->ni_fd);
+       }
+       /*
+        * Invariant; First open. Must init.
+        */
+       nino->ni_fpos = 0;
+       nino->ni_fd = fd;
+
+        /*
+         * Need to know whether we can seek on this
+         * descriptor.
+         */
+        nino->ni_seekok =
+            lseek_yod(nino->ni_fd, 0, SEEK_CUR) != 0 ? 0 : 1;
+
+       return 0;
+}
+
+static int
+yod_inop_close(struct inode *ino)
+{
+       struct yod_inode *nino = I2NI(ino);
+       int     err;
+
+       if (nino->ni_fd < 0)
+               abort();
+
+       assert(nino->ni_nopens);
+       if (--nino->ni_nopens)
+               return 0;
+
+       err = close_yod(nino->ni_fd);
+       if (err)
+               return -errno;
+
+       nino->ni_fd = -1;
+       nino->ni_fpos = 0;
+       return 0;
+}
+
+static int
+yod_inop_link(struct pnode *old, struct pnode *new)
+{
+       int     err;
+       char    *opath, *npath;
+
+       err = 0;
+
+       opath = _sysio_pb_path(old->p_base, '/');
+       npath = _sysio_pb_path(new->p_base, '/');
+       if (!(opath && npath)) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = link_yod(opath, npath);
+
+out:
+       if (opath)
+               free(opath);
+       if (npath)
+               free(npath);
+
+       return err;
+}
+
+static int
+yod_inop_unlink(struct pnode *pno)
+{
+       char    *path;
+       int     err = 0;
+
+       path = _sysio_pb_path(pno->p_base, '/');
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * For this driver, unlink is easy with open files. Since the
+        * file remains open to the system, too, the descriptors are still
+        * valid.
+        *
+        * Other drivers will have some difficulty here as the entry in the
+        * file system name space must be removed without sacrificing access
+        * to the file itself. In NFS this is done with a mechanism referred
+        * to as a `silly delete'. The file is moved to a temporary name
+        * (usually .NFSXXXXXX, where the X's are replaced by the PID and some
+        * unique characters) in order to simulate the proper semantic.
+        */
+       if (unlink_yod(path) != 0)
+               err = -errno;
+       free(path);
+       return err;
+}
+
+/*
+ * A helper function performing the real IO operation work.
+ *
+ * We don't really have async IO. We'll just perform the function
+ * now.
+ */
+static int
+doio(ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, struct yod_inode *),
+       struct ioctx *ioctx)
+{
+       struct yod_inode *nino = I2NI(ioctx->ioctx_ino);
+
+       ioctx->ioctx_cc =
+               _sysio_doio(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
+                           ioctx->ioctx_iov, ioctx->ioctx_iovlen,
+                           (ssize_t (*)(void *, size_t, 
+                                        _SYSIO_OFF_T, void *))f,
+                           nino);
+       if (ioctx->ioctx_cc < 0) {
+               ioctx->ioctx_errno = -ioctx->ioctx_cc;
+               ioctx->ioctx_cc = -1;
+               return -1;
+       }
+       nino->ni_fpos += ioctx->ioctx_cc;
+       ioctx->ioctx_done = 1;
+       return 0;
+}       
+
+static ssize_t
+yod_read_simple(void *buf,
+               size_t nbytes,
+               _SYSIO_OFF_T off,
+               struct yod_inode *nino)
+{
+       if (off != nino->ni_fpos) {
+               _SYSIO_OFF_T rtn;
+
+               rtn = lseek_yod(nino->ni_fd, off, SEEK_SET);
+               if (rtn < 0) 
+                       return -1;
+               nino->ni_fpos = rtn;
+       }
+       return read_yod(nino->ni_fd, buf, nbytes);
+}
+
+static int
+yod_inop_read(struct inode *ino __IS_UNUSED, struct ioctx *ioctx)
+{
+
+       return doio(yod_read_simple, ioctx);
+}
+
+static int
+yod_inop_rename(struct pnode *old, struct pnode *new)
+{
+       int     err;
+       char    *opath, *npath;
+
+       opath = _sysio_pb_path(old->p_base, '/');
+       npath = _sysio_pb_path(new->p_base, '/');
+       if (!(opath && npath)) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = rename_yod(opath, npath);
+
+out:
+       if (opath)
+               free(opath);
+       if (npath)
+               free(npath);
+
+       return err;
+}
+
+static ssize_t
+yod_write_simple(void *buf,
+               size_t nbytes,
+               _SYSIO_OFF_T off,
+               struct yod_inode *nino)
+{
+
+       if (off != nino->ni_fpos) {
+               _SYSIO_OFF_T rtn;
+
+               rtn = lseek_yod(nino->ni_fd, off, SEEK_SET);
+               if (rtn < 0) 
+                       return -1;
+               nino->ni_fpos = rtn;
+       }
+       return write_yod(nino->ni_fd, buf, nbytes);
+}
+
+static int
+yod_inop_write(struct inode *ino __IS_UNUSED, struct ioctx *ioctx)
+{
+
+       return doio(yod_write_simple, ioctx);
+}
+
+static _SYSIO_OFF_T
+yod_inop_pos(struct inode *ino, _SYSIO_OFF_T off)
+{
+       struct yod_inode *nino = I2NI(ino);
+       int     err;
+
+       err = lseek_yod(nino->ni_fd, off, SEEK_SET);
+       return err < 0 ? err : off;
+}
+
+static int
+yod_inop_iodone(struct ioctx *ioctxp __IS_UNUSED)
+{
+
+       /*
+        * It's always done in this driver. It completed when posted.
+        */
+       return 1;
+}
+
+static int
+yod_inop_fcntl(struct inode *ino __IS_UNUSED, int cmd, va_list ap __IS_UNUSED)
+{
+       switch (cmd) 
+       {
+       case F_DUPFD: /* do something to the ino */
+               break;
+       default:
+               errno = EINVAL; 
+               return -1;
+       }
+       return 0;
+               
+}
+
+static int
+yod_inop_mknod(struct pnode *pno __IS_UNUSED,
+                 mode_t mode __IS_UNUSED,
+                 dev_t dev __IS_UNUSED)
+{
+
+       return -ENOSYS;
+}
+
+#ifdef _HAVE_STATVFS
+static int
+yod_inop_statvfs(struct pnode *pno,
+                   struct inode *ino,
+                   struct intnl_statvfs *buf)
+{
+       char    *path;
+       int    rc;
+       struct statfs fs;
+
+       path = NULL;
+       if (!ino || I2NI(ino)->ni_fd < 0) {
+               path = _sysio_pb_path(pno->p_base, '/');
+               if (!path)
+                       return -ENOMEM;
+       }
+
+       /*
+        * The syscall interface does not support SYS_fstatvfs.
+        * Should possibly return ENOSYS, but thought it
+        * better to use SYS_fstatfs and fill in as much of
+        * the statvfs structure as possible.  This allows
+        * for more of a test of the sysio user interface.
+        */
+       rc =
+           path
+             ? statfs_yod(path, &fs)
+             : fstatfs_yod(I2NI(ino)->ni_fd, &fs);
+       if (path)
+               free(path);
+       if (rc < 0)
+               return -errno;
+
+       buf->f_bsize = fs.f_bsize;  /* file system block size */
+       buf->f_frsize = fs.f_bsize; /* file system fundamental block size */
+       buf->f_blocks = fs.f_blocks;
+       buf->f_bfree = fs.f_bfree;
+       buf->f_bavail = fs.f_bavail;
+       buf->f_files = fs.f_files;  /* Total number serial numbers */
+       buf->f_ffree = fs.f_ffree;  /* Number free serial numbers */
+       buf->f_favail = fs.f_ffree; /* Number free ser num for non-privileged*/
+       buf->f_fsid = fs.f_fsid.__val[1];
+       buf->f_flag = 0;            /* No equiv in statfs; maybe use type? */
+       buf->f_namemax = fs.f_namelen;
+       return 0;
+}
+#endif
+
+static int
+yod_inop_sync(struct inode *ino)
+{
+
+       assert(I2NI(ino)->ni_fd >= 0);
+
+       return fsync_yod(I2NI(ino)->ni_fd);
+}
+
+static int
+yod_inop_datasync(struct inode *ino)
+{
+
+       assert(I2NI(ino)->ni_fd >= 0);
+
+       return fsync_yod(I2NI(ino)->ni_fd);
+}
+
+static int
+yod_inop_ioctl(struct inode *ino __IS_UNUSED,
+                 unsigned long int request __IS_UNUSED,
+                 va_list ap __IS_UNUSED)
+{
+
+       /*
+        * I'm lazy. Maybe implemented later.
+        */
+       errno = ENOTTY;
+       return -1;
+}
+
+static void
+yod_inop_gone(struct inode *ino)
+{
+       struct yod_inode *nino = I2NI(ino);
+
+       if (nino->ni_fd)
+               (void )close(nino->ni_fd);
+       free(ino->i_private);
+}
+
+static void
+yod_fsop_gone(struct filesys *fs __IS_UNUSED)
+{
+
+       /*
+        * Do nothing. There is no private part maintained for the
+        * yod file interface. 
+        */
+}
diff --git a/libsysio/drivers/yod/fs_yod.h b/libsysio/drivers/yod/fs_yod.h
new file mode 100644 (file)
index 0000000..174b82d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Remote file system driver support.
+ */
+
+extern int _sysio_yod_init();
diff --git a/libsysio/drivers/yod/module.mk b/libsysio/drivers/yod/module.mk
new file mode 100644 (file)
index 0000000..1c2cc91
--- /dev/null
@@ -0,0 +1,10 @@
+if WITH_CPLANT_YOD
+YOD_SRCS = drivers/yod/fs_yod.c
+YOD_DRIVER_FLAGS = -DCPLANT_YOD
+else
+YOD_SRCS = 
+YOD_DRIVER_FLAGS = 
+endif
+
+# Bring yod files along in the distribution regardless
+YOD_EXTRA = include/cplant-yod.h drivers/yod/fs_yod.h drivers/yod/module.mk
diff --git a/libsysio/include/cplant-yod.h b/libsysio/include/cplant-yod.h
new file mode 100644 (file)
index 0000000..8aa4b50
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/* 
+ * cplant yod I/O functions
+ */
+extern int chmod_yod(const char* path, mode_t);
+extern int chown_yod(const char* path, uid_t, gid_t);
+extern int stat_yod(const char *path, struct stat *sbuf);
+extern int fstat_yod(int fd, struct stat *buf);
+#ifdef _HAVE_STATVFS
+extern int statfs_yod(const char *path, struct statfs *sbuf);
+extern int fstatfs_yod(int fd, struct statfs *buf);
+#endif
+extern int mkdir_yod(const char *path, mode_t mode);
+extern int rmdir_yod(const char *path);
+extern int getdirentries_yod(int fd, char *buf, size_t nbytes, loff_t *basep);
+extern int link_yod(const char *path1,  const char *path2);
+extern int unlink_yod(const char *path);
+extern int symlink_yod(const  char *path1, const char *path2 );
+extern int rename_yod( const char *path1, const char *path2 );
+extern int open_yod(const char *fname, int flags, mode_t mode);
+extern int close_yod(int);
+extern ssize_t write_yod(int fd, const void *buff, size_t nbytes);
+extern ssize_t read_yod(int fd, void *buff, size_t nbytes);
+extern int fsync_yod(int fd);
+extern int truncate_yod(const char *path, off_t length);
+extern int ftruncate_yod(int fd, long length);
+extern off_t lseek_yod(int fd, off_t offset, int whence);
diff --git a/libsysio/include/dev.h b/libsysio/include/dev.h
new file mode 100644 (file)
index 0000000..0fe459b
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Device support.
+ */
+
+/*
+ * Make a device number, composed of major and minor parts. We *assume* that
+ * the system version of a dev_t is 16 bits or more.
+ */
+#define SYSIO_MKDEV(major, minor) \
+       ((((major) & 0xff) << 8) | ((minor) & 0xff))
+
+/*
+ * Return major unit given dev number.
+ */
+#define SYSIO_MAJOR_DEV(dev) \
+       (((dev) >> 8) & 0xff)
+
+/*
+ * Return minor unit given dev number.
+ */
+#define SYSIO_MINOR_DEV(dev) \
+       ((dev) & 0xff)
+
+extern const struct inode_ops _sysio_nodev_ops;
+
+#define _sysio_nodev_inop_lookup \
+       (int (*)(struct pnode *, \
+                struct inode **, \
+                struct intent *, \
+                const char *))_sysio_do_illop
+#define _sysio_nodev_inop_getattr \
+       (int (*)(struct pnode *, \
+                struct inode *, \
+                struct intnl_stat *))_sysio_do_ebadf
+#define _sysio_nodev_inop_setattr \
+       (int (*)(struct pnode *, \
+                struct inode *, \
+                unsigned , \
+                struct intnl_stat *))_sysio_do_ebadf
+#define _sysio_nodev_getdirentries \
+       (ssize_t (*)(struct inode *, \
+                    char *, \
+                    size_t , \
+                    _SYSIO_OFF_T *))_sysio_do_illop
+#define _sysio_nodev_inop_mkdir \
+       (int (*)(struct pnode *, \
+                mode_t))_sysio_do_illop
+#define _sysio_nodev_inop_rmdir \
+       (int (*)(struct pnode *))_sysio_do_illop
+#define _sysio_nodev_inop_symlink \
+       (int (*)(struct pnode *, \
+                const char *))_sysio_do_illop
+#define _sysio_nodev_inop_readlink \
+       (int (*)(struct pnode *, \
+                char *, \
+                size_t))_sysio_do_illop
+#define _sysio_nodev_inop_open \
+       (int (*)(struct pnode *, \
+                int, \
+                mode_t))_sysio_do_enoent
+#define _sysio_nodev_inop_close \
+       (int (*)(struct inode *))_sysio_do_ebadf
+#define _sysio_nodev_inop_link \
+       (int (*)(struct pnode *, struct pnode *))_sysio_do_illop
+#define _sysio_nodev_inop_unlink \
+       (int (*)(struct pnode *))_sysio_do_illop
+#define _sysio_nodev_inop_rename \
+       (int (*)(struct pnode *, struct pnode *))_sysio_do_illop
+#define _sysio_nodev_inop_read \
+       (int (*)(struct inode *, \
+                struct ioctx *))_sysio_do_ebadf
+#define _sysio_nodev_inop_write \
+       (int (*)(struct inode *, \
+                struct ioctx *))_sysio_do_ebadf
+#define _sysio_nodev_inop_pos \
+       (_SYSIO_OFF_T (*)(struct inode *, _SYSIO_OFF_T))_sysio_do_ebadf
+#define _sysio_nodev_inop_iodone \
+       (int (*)(struct ioctx *))_sysio_do_einval
+#define _sysio_nodev_inop_fcntl \
+       (int (*)(struct inode *, \
+                int, \
+                va_list))_sysio_do_ebadf
+#define _sysio_nodev_inop_sync \
+       (int (*)(struct inode *))_sysio_do_ebadf
+#define _sysio_nodev_inop_datasync \
+       (int (*)(struct inode *))_sysio_do_ebadf
+#define _sysio_nodev_inop_ioctl \
+       (int (*)(struct inode *, \
+                unsigned long int, \
+                va_list))_sysio_do_ebadf
+#define _sysio_nodev_inop_mknod \
+       (int (*)(struct pnode *, \
+                mode_t, \
+                dev_t))_sysio_do_illop
+#ifdef _HAVE_STATVFS
+#define _sysio_nodev_inop_statvfs \
+       (int (*)(struct pnode *, \
+                struct inode *, \
+                struct intnl_statvfs *))_sysio_do_illop
+#endif
+#define _sysio_nodev_inop_gone \
+       (void (*)(struct inode *ino))_sysio_do_noop
+
+extern int _sysio_dev_init(void);
+extern dev_t _sysio_dev_alloc(void);
+extern struct inode_ops *_sysio_dev_lookup(mode_t mode, dev_t dev);
+extern int _sysio_char_dev_register(int major,
+                                   const char *name,
+                                   struct inode_ops *ops);
diff --git a/libsysio/include/file.h b/libsysio/include/file.h
new file mode 100644 (file)
index 0000000..ed15f6b
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Open file support.
+ */
+
+/*
+ * A file record is maintained for each open file in the system. It holds
+ * all the info necessary to track the context and parameters for the
+ * operations that may be performed.
+ */
+struct file {
+       struct inode *f_ino;                            /* path node */
+       _SYSIO_OFF_T f_pos;                             /* current stream pos */
+       unsigned f_ref;                                 /* ref count */
+       int     f_flags;                                /* open/fcntl flags */
+};
+
+/*
+ * Reference a file record.
+ */
+#define F_REF(fil) \
+       do { \
+               (fil)->f_ref++; \
+               assert((fil)->f_ref); \
+               I_REF((fil)->f_ino); \
+       } while (0)
+
+/*
+ * Release reference to a file record.
+ */
+#define F_RELE(fil) \
+       do { \
+               struct inode *ino; \
+               \
+               assert((fil)->f_ref); \
+               (fil)->f_ref--; \
+               ino = (fil)->f_ino; \
+               if (!(fil)->f_ref) \
+                       _sysio_fgone(fil); \
+               I_RELE(ino); \
+       } while (0)
+
+/*
+ * Init file record.
+ *
+ * NB: Don't forget to take a reference to the inode too!
+ */
+#define _SYSIO_FINIT(fil, ino, flags) \
+       do { \
+               (fil)->f_ino = (ino); \
+               (fil)->f_pos = 0; \
+               (fil)->f_ref = 1; \
+               (fil)->f_flags = (flags); \
+       } while (0)
+
+struct ioctx;
+
+extern struct file *_sysio_fnew(struct inode *ino, int flags);
+extern void _sysio_fgone(struct file *fil);
+extern void _sysio_fcompletio(struct ioctx *ioctx, struct file *fil);
+extern int _sysio_fd_close(int fd);
+extern struct file *_sysio_fd_find(int fd);
+extern int _sysio_fd_set(struct file *fil, int fd);
+extern int _sysio_fd_dup2(int oldfd, int newfd);
+extern int _sysio_fd_close_all(void);
+#if ZERO_SUM_MEMORY
+extern void _sysio_fd_shutdown(void);
+#endif
diff --git a/libsysio/include/fs.h b/libsysio/include/fs.h
new file mode 100644 (file)
index 0000000..8c7e782
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * File system or volume support.
+ */
+
+struct filesys;
+
+struct pnode;
+struct mount;
+
+/*
+ * File system switch operations.
+ */
+struct fssw_ops {
+       int     (*fsswop_mount)(const char *source,
+                               unsigned flags,
+                               const void *data,
+                               struct pnode *tocover,
+                               struct mount **mntp);
+};
+
+/*
+ * File system switch entry record.
+ *
+ * Each available file system or volume access driver is represented by
+ * one of these switch entries in the switch.
+ */
+struct fsswent {
+       const char *fssw_name;                          /* entry name */
+       LIST_ENTRY(fsswent) fssw_link;                  /* link to next */
+       struct fssw_ops fssw_ops;                       /* operations */
+};
+
+/*
+ * Init file system switch entry record.
+ */
+#define FSSWENT_INIT(fsswent, name, ops) \
+       do { \
+               (fsswent)->fssw_name = (name); \
+               (fsswent)->fssw_ops = (ops); \
+       } while (0)
+
+struct inode;
+
+/*
+ * File system operations.
+ */
+struct filesys_ops {
+       void    (*fsop_gone)(struct filesys *);
+};
+
+/*
+ * Define the desired size of the file system record's inode table. This should
+ * probably be something fancy that tries to use up a system page, or the
+ * like. I'm not feeling adventurous right now though. It is prime though.
+ * That should help out the hash.
+ */
+#ifndef FS_ITBLSIZ
+#define FS_ITBLSIZ     503
+#endif
+
+/*
+ * Inode list head record.
+ */
+LIST_HEAD(itable_entry, inode);
+
+/*
+ * A filesys record is maintained for each active file system or volume.
+ */
+struct filesys {
+       dev_t   fs_dev;                                 /* device ID */
+       unsigned fs_ref;                                /* soft ref count */
+       unsigned fs_flags;                              /* flags (see below) */
+       struct filesys_ops fs_ops;                      /* operations */
+       void    *fs_private;                            /* driver data */
+       struct itable_entry fs_itbl[FS_ITBLSIZ];        /* inodes hash */
+       unsigned long fs_id;                            /* ID */
+       size_t  fs_bsize;                               /* block size */
+};
+
+#define FS_F_RO                        0x01                    /* read-only */
+
+/*
+ * Init file system record.
+ */
+#define FS_INIT(fs, flags, ops, private) \
+       do { \
+               size_t  __i; \
+               struct itable_entry *__head; \
+ \
+               (fs)->fs_ref = 1; \
+               (fs)->fs_flags = (flags); \
+               (fs)->fs_ops = *(ops); \
+               (fs)->fs_private = (private); \
+               __i = FS_ITBLSIZ; \
+               __head = (fs)->fs_itbl; \
+               do { \
+                       LIST_INIT(__head); \
+                       __head++; \
+               } while (--__i); \
+       } while (0)
+
+/*
+ * Reference file system record.
+ */
+#define FS_REF(fs) \
+       do { \
+               ++(fs)->fs_ref; \
+               assert((fs)->fs_ref); \
+       } while (0)
+
+/*
+ * Release reference to file system record.
+ */
+#define FS_RELE(fs) \
+       do { \
+               assert((fs)->fs_ref); \
+               if (!--(fs)->fs_ref) \
+                       _sysio_fs_gone(fs); \
+       } while (0)
+
+extern struct fsswent *_sysio_fssw_lookup(const char *name);
+extern int _sysio_fssw_register(const char *name, struct fssw_ops *ops);
+extern struct filesys * _sysio_fs_new(struct filesys_ops *ops,
+                                     unsigned mask,
+                                     void *private);
+extern void _sysio_fs_gone(struct filesys *fs);
+#if ZERO_SUM_MEMORY
+extern void _sysio_fssw_shutdown(void);
+#endif
diff --git a/libsysio/include/inode.h b/libsysio/include/inode.h
new file mode 100644 (file)
index 0000000..d6ee2ff
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#if defined(AUTOMOUNT_FILE_NAME) && !defined(MAX_MOUNT_DEPTH)
+/*
+ * Maximum number of automounts to attempt in path traversal.
+ */
+#define MAX_MOUNT_DEPTH                64
+#endif
+
+/*
+ * Each i-node is uniquely identified by a file identifier, supplied by
+ * the relevant file system driver. The i-node number returned in the getattrs
+ * call is not always enough.
+ */
+struct file_identifier {
+    void    *fid_data;
+    size_t  fid_len;
+};
+
+struct pnode;
+struct inode;
+struct intent;
+struct intnl_dirent;
+struct intnl_stat;
+#ifdef _HAVE_STATVFS
+struct intnl_statvfs;
+#endif
+struct io_arguments;
+struct ioctx;
+
+/*
+ * Operations on i-nodes.
+ *
+ * Should this be split up into file and name space operations?
+ */
+struct inode_ops {
+    int (*inop_lookup)(struct pnode *pno,
+                       struct inode **inop,
+                       struct intent *intnt,
+                       const char *path);
+    int (*inop_getattr)(struct pnode *pno,
+                        struct inode *ino,
+                        struct intnl_stat *stbuf);
+    int (*inop_setattr)(struct pnode *pno,
+                        struct inode *ino,
+                        unsigned mask,
+                        struct intnl_stat *stbuf);
+    ssize_t (*inop_getdirentries)(struct inode *ino,
+                                 char *buf,
+                                 size_t nbytes,
+                                 _SYSIO_OFF_T *basep);
+    int (*inop_mkdir)(struct pnode *pno, mode_t mode);
+    int (*inop_rmdir)(struct pnode *pno);
+    int (*inop_symlink)(struct pnode *pno, const char *data);
+    int (*inop_readlink)(struct pnode *pno, char *buf, size_t bufsiz);
+    int (*inop_open)(struct pnode *pno, int flags, mode_t mode);
+    int (*inop_close)(struct inode *ino);
+    int (*inop_link)(struct pnode *old, struct pnode *new);
+    int (*inop_unlink)(struct pnode *pno);
+    int (*inop_rename)(struct pnode *old, struct pnode *new);
+    int (*inop_read)(struct inode *ino, struct ioctx *ioctx);
+    int (*inop_write)(struct inode *ino, struct ioctx *ioctx);
+    _SYSIO_OFF_T (*inop_pos)(struct inode *ino, _SYSIO_OFF_T off);
+    int (*inop_iodone)(struct ioctx *iocp);
+    int (*inop_fcntl)(struct inode *ino, int cmd, va_list ap);
+    int (*inop_sync)(struct inode *ino);
+    int (*inop_datasync)(struct inode *ino);
+    int (*inop_ioctl)(struct inode *ino, unsigned long int request, va_list ap);
+    int (*inop_mknod)(struct pnode *pno, mode_t mode, dev_t dev);
+#ifdef _HAVE_STATVFS
+    int (*inop_statvfs)(struct pnode *pno,
+                        struct inode *ino,
+                        struct intnl_statvfs *buf);
+#endif
+    void    (*inop_gone)(struct inode *ino);
+};
+
+/*
+ * Values for the mask to inop_setattr.
+ */
+#define SETATTR_MODE        0x01
+#define SETATTR_MTIME       0x02
+#define SETATTR_ATIME       0x04
+#define SETATTR_UID         0x08
+#define SETATTR_GID         0x10
+#define SETATTR_LEN         0x20
+
+/*
+ * An i-node record is maintained for each file object in the system.
+ */
+struct inode {
+    LIST_ENTRY(inode) i_link;                           /* FS i-nodes link */
+    unsigned
+       i_immune                        : 1,            /* immune from GC */
+       i_zombie                        : 1;            /* stale inode */
+    unsigned i_ref;                                     /* soft ref counter */
+    mode_t  i_mode;                                     /* mode (see stat.h) */
+    dev_t   i_rdev;                                    /* dev (if device) */
+    struct inode_ops i_ops;                             /* operations */
+    struct filesys *i_fs;                               /* file system ptr */
+    struct file_identifier *i_fid;                      /* file ident */
+    void    *i_private;                                 /* driver data */
+    TAILQ_ENTRY(inode) i_nodes;                         /* all i-nodes link */
+};
+
+/*
+ * Init an i-node record.
+ */
+#define I_INIT(ino, fs, mode, rdev, ops, fid, immunity, private) \
+    do { \
+        (ino)->i_immune = (immunity) ? 1 : 0; \
+        (ino)->i_zombie = 0; \
+        (ino)->i_ref = 0; \
+        (ino)->i_mode = (mode); \
+        (ino)->i_rdev = (rdev); \
+        (ino)->i_ops = *(ops); \
+        (ino)->i_fs = (fs); \
+        (ino)->i_fid = (fid); \
+        (ino)->i_private = (private); \
+    } while (0)
+
+/*
+ * Take soft reference to i-node.
+ */
+#define I_REF(ino) \
+    do { \
+        TAILQ_REMOVE(&_sysio_inodes, (ino), i_nodes); \
+        TAILQ_INSERT_TAIL(&_sysio_inodes, (ino), i_nodes); \
+        (ino)->i_ref++; \
+        assert((ino)->i_ref); \
+    } while (0)
+
+/*
+ * Release soft reference to i-node.
+ */
+#define I_RELE(ino) \
+    do { \
+        assert((ino)->i_ref); \
+       if (!--(ino)->i_ref && (ino)->i_zombie) \
+               _sysio_i_gone(ino); \
+    } while (0)
+
+/*
+ * Attempt to kill an inode.
+ */
+#define I_GONE(ino) \
+    do { \
+       _sysio_i_undead(ino); \
+       I_RELE(ino); \
+    } while (0)
+
+/*
+ * The "quick string" record (inspired by the structure of the same name
+ * from Linux) is used to pass a string without delimiters as well as useful
+ * information about the string.
+ */
+struct qstr {
+    const char *name;
+    size_t  len;
+    unsigned hashval;
+};
+
+/*
+ * A path node is an entry in a directory. It may have many aliases, one
+ * for each name space in which it occurs. This record holds the
+ * common information.
+ */
+struct pnode_base {
+    struct qstr pb_name;                                /* entry name */
+    struct inode *pb_ino;                               /* inode */
+    LIST_HEAD(, pnode_base) pb_children;                /* children if a dir */
+    LIST_ENTRY(pnode_base) pb_sibs;                     /* links to siblings */
+    LIST_ENTRY(pnode_base) pb_names;                    /* near names links */
+    LIST_HEAD(, pnode) pb_aliases;                      /* aliases */
+    struct pnode_base *pb_parent;                       /* parent */
+};
+
+/*
+ * Since a file system may be multiply mounted, in different parts of the local
+ * tree, a file system object may appear in different places. We handle that
+ * with aliases. There is one pnode for every alias the system is tracking.
+ *
+ * Name space traversal depends heavily on the interpretation of many
+ * of the fields in this structure. For that reason a detailed discussion
+ * of the various fields is given.
+ *
+ * The reference field records soft references to the record. For instance,
+ * it tracks file and directory opens. It does not track sibling references,
+ * though, as those are hard references and can be found by examining the
+ * aliases list in the base part of the node.
+ *
+ * The parent value points to the parent directory for this entry, in the
+ * *system* name space -- Not the mounted volumes. If you want to examine
+ * the moutned volume name space, use the base record.
+ *
+ * The base value points to the base path node information. It is info common
+ * to all of the aliases.
+ *
+ * The mount value points to the mount record for the rooted name space in
+ * which the alias is found. Notably, if a node is the root of a sub-tree then
+ * the mount record, among other things, indicates another node
+ * (in another sub-tree) that is covered by this one.
+ *
+ * Another sub-tree, mounted on this node, is indicated by a non-null cover.
+ * The pnode pointed to, then, is the root of the mounted sub-tree.
+ *
+ * The links list entry holds pointers to other aliases for the base path
+ * node entry.
+ *
+ * The nodes link is bookkeeping.
+ */
+struct pnode {
+    unsigned p_ref;                                     /* soft ref count */
+    struct pnode *p_parent;                             /* parent */
+    struct pnode_base *p_base;                          /* base part */
+    struct mount *p_mount;                              /* mount info */
+    struct pnode *p_cover;                              /* covering pnode */
+    LIST_ENTRY(pnode) p_links;                          /* other aliases */
+    TAILQ_ENTRY(pnode) p_nodes;                         /* all nodes links */
+};
+
+/*
+ * Reference path-tree node.
+ */
+#define P_REF(pno) \
+    do { \
+        TAILQ_REMOVE(&_sysio_pnodes, (pno), p_nodes); \
+        TAILQ_INSERT_TAIL(&_sysio_pnodes, (pno), p_nodes); \
+        (pno)->p_ref++; \
+        assert((pno)->p_ref); \
+    } while (0)
+
+/*
+ * Release reference to path-tree node.
+ */
+#define P_RELE(pno) \
+    do { \
+        assert((pno)->p_ref); \
+        --(pno)->p_ref; \
+    } while (0)
+
+/*
+ * An intent record allows callers of namei and lookup to pass some information
+ * about what they want to accomplish in the end.
+ */
+struct intent {
+    unsigned int_opmask;                
+    void    *int_arg1;
+    void    *int_arg2;
+};
+
+/*
+ * Intent operations.
+ */
+#define INT_GETATTR         0x01                        /* get attrs */
+#define INT_SETATTR         0x02                        /* set attrs */
+#define INT_UPDPARENT       0x04                        /* insert/delete */
+#define INT_OPEN            0x08                        /* open */
+#define INT_CREAT           (INT_UPDPARENT|0x10)        /* insert */
+#define INT_READLINK        0x12                        /* readlink */
+
+#define INTENT_INIT(intnt, mask, arg1, arg2) \
+    do { \
+        (intnt)->int_opmask = (mask); \
+        (intnt)->int_arg1 = (arg1); \
+        (intnt)->int_arg2 = (arg2); \
+    } while (0)
+
+/*
+ * Bundled up arguments to _sysio_path_walk.
+ */
+struct nameidata {
+    unsigned nd_flags;                                  /* flags (see below) */
+    const char *nd_path;                                /* path arg */
+    struct pnode *nd_pno;                               /* returned pnode */
+    struct pnode *nd_root;                              /* system/user root */
+    struct intent *nd_intent;                           /* intent (NULL ok) */
+    unsigned nd_slicnt;                                        /* symlink indirects */
+#ifdef AUTOMOUNT_FILE_NAME
+    unsigned nd_amcnt;                                 /* automounts */
+#endif
+};
+
+/*
+ * Values for nameidata flags field.
+ */
+#define ND_NOFOLLOW     0x01                           /* no follow symlinks */
+#define ND_NEGOK        0x02                           /* last missing is ok */
+
+#ifdef AUTOMOUNT_FILE_NAME
+#define _ND_INIT_AUTOMOUNT(nd) ((nd)->nd_amcnt = 0)
+#else
+#define _ND_INIT_AUTOMOUNT(nd)
+#endif
+
+#define _ND_INIT_OTHERS(nd) \
+    _ND_INIT_AUTOMOUNT(nd)
+
+/*
+ * Init nameidata record.
+ */
+#define ND_INIT(nd, flags, path, root, intnt) \
+    do { \
+       (nd)->nd_flags = (flags); \
+        (nd)->nd_path = (path); \
+        (nd)->nd_pno = NULL; \
+        (nd)->nd_root = (root); \
+        (nd)->nd_intent = (intnt); \
+        (nd)->nd_slicnt = 0; \
+       _ND_INIT_OTHERS(nd); \
+    } while (0)
+
+/*
+ * IO completion callback record.
+ */
+struct ioctx_callback {
+    TAILQ_ENTRY(ioctx_callback) iocb_next;             /* list link */
+    void    (*iocb_f)(struct ioctx *, void *);         /* cb func */
+    void    *iocb_data;                                /* cb data */
+};
+
+/*
+ * All IO internally is done with an asynchronous mechanism. This record
+ * holds the completion information. It's too big :-(
+ */
+struct ioctx {
+    LIST_ENTRY(ioctx) ioctx_link;                       /* AIO list link */
+    unsigned
+        ioctx_fast                      : 1,           /* from stack space */
+       ioctx_done                      : 1,            /* transfer complete */
+       ioctx_write                     : 1;            /* op is a write */
+    ioid_t  ioctx_id;                                   /* unique ident */
+    struct inode *ioctx_ino;                            /* i-node */
+    const struct iovec *ioctx_iov;                      /* scatter/gather vec */
+    size_t  ioctx_iovlen;                               /* iovec length */
+    const struct intnl_xtvec *ioctx_xtv;                /* extents */
+    size_t  ioctx_xtvlen;                               /* xtv length */
+    ssize_t ioctx_cc;                                   /* rtn char count */
+    int ioctx_errno;                                    /* error number */
+    TAILQ_HEAD(, ioctx_callback) ioctx_cbq;             /* callback queue */
+    void *ioctx_private;                               /* driver data */
+};
+
+/*
+ * Init IO context record.
+ */
+#define IOCTX_INIT(ioctx, fast, id, wr, ino, iov, iovlen, xtv, xtvlen) \
+    do { \
+       (ioctx)->ioctx_fast = (fast); \
+       (ioctx)->ioctx_done = 0; \
+       (ioctx)->ioctx_write = (wr) ? 1 : 0; \
+        (ioctx)->ioctx_id = (id); \
+        (ioctx)->ioctx_ino = (ino); \
+        (ioctx)->ioctx_iov = (iov); \
+        (ioctx)->ioctx_iovlen = (iovlen); \
+        (ioctx)->ioctx_xtv = (xtv); \
+        (ioctx)->ioctx_xtvlen = (xtvlen); \
+        (ioctx)->ioctx_cc = 0; \
+        (ioctx)->ioctx_errno = 0; \
+        TAILQ_INIT(&(ioctx)->ioctx_cbq); \
+        (ioctx)->ioctx_private = NULL; \
+    } while (0)
+
+/*
+ * Return whether a pnode/inode is on a read-only mount or file system.
+ */
+#define IS_RDONLY(pno, ino) \
+       ((((struct pnode *)(pno)) && \
+         ((((struct pnode *)(pno))->p_mount->mnt_flags & MOUNT_F_RO) || \
+          (((struct pnode *)(pno))->p_base->pb_ino && \
+           (((struct pnode *)(pno))->p_base->pb_ino->i_fs->fs_flags & \
+            FS_F_RO)))) || \
+        (((struct inode *)(ino)) && \
+         (((struct inode *)(ino))->i_fs->fs_flags & FS_F_RO)))
+
+extern struct pnode *_sysio_root;
+
+extern TAILQ_HEAD(inodes_head, inode) _sysio_inodes;
+extern TAILQ_HEAD(pnodes_head, pnode) _sysio_pnodes;
+
+extern int _sysio_i_init(void);
+#if ZERO_SUM_MEMORY
+extern void _sysio_i_shutdown(void);
+#endif
+extern struct inode *_sysio_i_new(struct filesys *fs,
+                                  struct file_identifier *fid,
+                                  mode_t type,
+                                  dev_t rdev,
+                                 unsigned immunity,
+                                  struct inode_ops *ops,
+                                  void *private);
+extern struct inode *_sysio_i_find(struct filesys *fs,
+                                   struct file_identifier *fid);
+extern void _sysio_i_gone(struct inode *ino);
+extern void _sysio_i_undead(struct inode *ino);
+extern int _sysio_p_find_alias(struct pnode *parent,
+                               struct qstr *name,
+                               struct pnode **pnop);
+extern int _sysio_p_validate(struct pnode *pno,
+                             struct intent *intnt,
+                             const char *path);
+extern struct pnode_base *_sysio_pb_new(struct qstr *name,
+                                        struct pnode_base *parent,
+                                        struct inode *ino);
+extern void _sysio_pb_gone(struct pnode_base *pb);
+extern struct pnode *_sysio_p_new_alias(struct pnode *parent,
+                                        struct pnode_base *pb,
+                                        struct mount *mnt);
+extern void _sysio_p_gone(struct pnode *pno);
+extern size_t _sysio_p_prune(struct pnode *root);
+extern int _sysio_p_kill_all(struct pnode *root);
+extern char *_sysio_pb_path(struct pnode_base *pb, char separator);
+extern int _sysio_setattr(struct pnode *pno,
+                         struct inode *ino,
+                         unsigned mask,
+                         struct intnl_stat *stbuf);
+extern void _sysio_do_noop(void);
+extern void _sysio_do_illop(void);
+extern int _sysio_do_ebadf(void);
+extern int _sysio_do_einval(void);
+extern int _sysio_do_enoent(void);
+extern int _sysio_do_espipe(void);
+extern int _sysio_do_eisdir(void);
+extern int _sysio_do_enosys(void);
+extern int _sysio_path_walk(struct pnode *parent, struct nameidata *nd);
+#ifdef AUTOMOUNT_FILE_NAME
+extern void _sysio_next_component(const char *path, struct qstr *name);
+#endif
+extern int _sysio_namei(struct pnode *pno,
+                        const char *path,
+                        unsigned flags,
+                        struct intent *intnt,
+                        struct pnode **pnop);
+extern int _sysio_p_chdir(struct pnode *pno);
+extern int _sysio_ioctx_init(void);
+extern void _sysio_ioctx_enter(struct ioctx *ioctx);
+extern struct ioctx *_sysio_ioctx_new(struct inode *ino,
+                                     int wr,
+                                      const struct iovec *iov,
+                                     size_t iovlen,
+                                      const struct intnl_xtvec *xtv,
+                                     size_t xtvlen);
+extern int _sysio_ioctx_cb(struct ioctx *ioctx,
+                          void (*f)(struct ioctx *, void *),
+                          void *data);
+extern void _sysio_ioctx_cb_free(struct ioctx_callback *cb);
+extern struct ioctx *_sysio_ioctx_find(ioid_t id);
+extern ssize_t _sysio_ioctx_wait(struct ioctx *ioctx);
+extern void _sysio_ioctx_complete(struct ioctx *ioctx);
+extern ssize_t _sysio_validx(const struct intnl_xtvec *xtv, size_t xtvlen,
+                            const struct iovec *iov, size_t iovlen,
+                            _SYSIO_OFF_T limit);
+extern ssize_t _sysio_enumerate_extents(const struct intnl_xtvec *xtv,
+                                       size_t xtvlen,
+                                       const struct iovec *iov,
+                                       size_t iovlen,
+                                       ssize_t (*f)(const struct iovec *,
+                                                    int,
+                                                    _SYSIO_OFF_T,
+                                                    ssize_t,
+                                                    void *),
+                                       void *arg);
+extern ssize_t _sysio_enumerate_iovec(const struct iovec *iov,
+                                     size_t count,
+                                     _SYSIO_OFF_T off,
+                                     ssize_t limit,
+                                     ssize_t (*f)(void *,
+                                                  size_t,
+                                                  _SYSIO_OFF_T,
+                                                  void *),
+                                     void *arg);
+extern ssize_t _sysio_doio(const struct intnl_xtvec *xtv, size_t xtvlen,
+                          const struct iovec *iov, size_t iovlen,
+                          ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),
+                          void *arg);
+extern int _sysio_open(struct pnode *pno, int flags, mode_t mode);
diff --git a/libsysio/include/module.mk b/libsysio/include/module.mk
new file mode 100644 (file)
index 0000000..ce1c427
--- /dev/null
@@ -0,0 +1,4 @@
+INCLUDE_EXTRA = include/dev.h include/file.h include/fs.h \
+       include/inode.h include/mount.h include/sysio.h \
+       include/sysio-symbols.h include/cplant-yod.h \
+       include/module.mk include/xtio.h
diff --git a/libsysio/include/mount.h b/libsysio/include/mount.h
new file mode 100644 (file)
index 0000000..24f631d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Mount support.
+ */
+
+struct filesys;
+struct pnode;
+
+/*
+ * Each file system may be mounted multiple times and in various places
+ * in the name space. The mount record maintains the binding information
+ * between the system name space and the file system's.
+ */
+struct mount {
+       struct filesys *mnt_fs;                         /* file system */
+       unsigned mnt_flags;                             /* flags (see below) */
+       struct pnode *mnt_root;                         /* fs sub-tree root */
+       struct pnode *mnt_covers;                       /* covered pnode */
+       LIST_ENTRY(mount) mnt_link;                     /* link to next */
+};
+
+/*
+ * Mount flags definitions.
+ */
+#define MOUNT_F_RO             0x01                    /* read-only */
+#ifdef AUTOMOUNT_FILE_NAME
+#define MOUNT_F_AUTO           0x02                    /* automount enabled */
+#endif
+
+#ifdef AUTOMOUNT_FILE_NAME
+extern struct qstr _sysio_mount_file_name;
+#endif
+
+struct pnode_base;
+
+extern int _sysio_mount_init(void);
+extern int _sysio_do_mount(struct filesys *fs,
+                          struct pnode_base *rootpb,
+                          unsigned flags,
+                          struct pnode *tocover,
+                          struct mount **mntp);
+extern int _sysio_do_unmount(struct mount *fs);
+extern int _sysio_mount_root(const char *source,
+                            const char *type,
+                            unsigned flags,
+                            const void *data);
+extern int _sysio_mount(struct pnode *cwd,
+                       const char *source,
+                       const char *target,
+                       const char *filesystemtype,
+                       unsigned long mountflags,
+                       const void *data);
+extern int _sysio_unmount_all(void);
+#ifdef AUTOMOUNT_FILE_NAME
+extern int _sysio_automount(struct pnode *mntpno);
+#endif
diff --git a/libsysio/include/namespace.h b/libsysio/include/namespace.h
new file mode 100644 (file)
index 0000000..23c1f78
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/* 
+ * Boot time namespace assembly function
+ */
+extern int run_cmds(char *buf);
+
diff --git a/libsysio/include/sysio-symbols.h b/libsysio/include/sysio-symbols.h
new file mode 100644 (file)
index 0000000..4b7cf56
--- /dev/null
@@ -0,0 +1,26 @@
+#if defined(HAVE_ASM_WEAK_DIRECTIVE) || defined(HAVE_ASM_WEAKEXT_DIRECTIVE)
+#define HAVE_WEAK_SYMBOLS
+#endif
+
+#define STRINGOF(x) #x
+
+/*
+ * Define alias, asym, as a strong alias for symbol, sym.
+ */
+#define sysio_sym_strong_alias(sym, asym) \
+  extern __typeof(sym) asym __attribute__((alias(STRINGOF(sym))));
+
+#ifdef HAVE_WEAK_SYMBOLS
+
+/*
+ * Define alias, asym, as a strong alias for symbol, sym.
+ */
+#define sysio_sym_weak_alias(sym, asym) \
+  extern __typeof(sym) asym __attribute__((weak, alias(STRINGOF(sym))));
+#else /* !defined(HAVE_ASM_WEAK_DIRECTIVE) */
+
+/*
+ * Weak symbols not supported. Make it a strong alias then.
+ */
+#define sysio_sym_weak_alias(sym, asym) sysio_sym_strong_alias(sym, asym)
+#endif
diff --git a/libsysio/include/sysio.h b/libsysio/include/sysio.h
new file mode 100644 (file)
index 0000000..fb05d75
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2004 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * System IO common information.
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#ifndef _IOID_T_DEFINED
+#define _IOID_T_DEFINED
+/*
+ * FIXME:
+ *
+ * This section about ioid_t and it's failure belong in <sys/types.h>
+ */
+typedef void *ioid_t;
+
+#define IOID_FAIL                      0
+#endif
+
+#if !defined(__IS_UNUSED) && defined(__GNUC__)
+#define __IS_UNUSED    __attribute__ ((unused))
+#else
+#define __IS_UNUSED
+#endif
+
+#ifndef PATH_SEPARATOR
+/*
+ * Path separator.
+ */
+#define PATH_SEPARATOR                 '/'
+#endif
+
+#ifndef MAX_SYMLINK
+/*
+ * Max recursion depth allowed when resoving symbolic links.
+ */
+#define MAX_SYMLINK                    250
+#endif
+
+#ifndef _LARGEFILE64_SOURCE
+/*
+ * Not glibc I guess. Define this ourselves.
+ */
+#define _LARGEFILE64_SOURCE            0
+#endif
+
+/*
+ * Define internal file-offset type and it's maximum value.
+ */
+#if _LARGEFILE64_SOURCE
+#define _SYSIO_OFF_T                   off64_t
+#ifdef LLONG_MAX
+#define _SYSIO_OFF_T_MAX               (LLONG_MAX)
+#else
+/*
+ * Don't have LLONG_MAX before C99. We'll need to define it ourselves.
+ */
+#define _SYSIO_OFF_T_MAX               (9223372036854775807LL)
+#endif
+#else
+#define _SYSIO_OFF_T                   off_t
+#define _SYSIO_OFF_T_MAX               LONG_MAX
+#endif
+
+/*
+ * Internally, all directory entries are carried in the 64-bit capable
+ * structure.
+ */
+#if _LARGEFILE64_SOURCE
+#define intnl_dirent dirent64
+#else
+#define intnl_dirent dirent
+#endif
+struct dirent;
+
+/*
+ * Internally, all file status is carried in the 64-bit capable
+ * structure.
+ */
+#if _LARGEFILE64_SOURCE
+#define intnl_stat stat64
+#else
+#define intnl_stat stat
+#endif
+struct stat;
+
+#ifdef _HAVE_STATVFS
+#if _LARGEFILE64_SOURCE
+#define intnl_statvfs statvfs64
+#else
+#define intnl_statvfs statvfs
+#define INTNL_STATVFS_IS_NATURAL       1
+#endif
+struct statvfs;
+struct intnl_statvfs;
+#endif
+
+/*
+ * Internally, all file status is carried in the 64-bit capable
+ * structure.
+ */
+#if _LARGEFILE64_SOURCE
+#define intnl_xtvec xtvec64
+#else
+#define intnl_xtvec xtvec
+#endif
+struct intnl_xtvec;
+
+struct iovec;
+
+struct utimbuf;
+
+struct intnl_stat;
+
+struct pnode;
+
+extern struct pnode *_sysio_cwd;
+
+extern mode_t _sysio_umask;
+
+extern int _sysio_init(void);
+extern void _sysio_shutdown(void);
+extern int _sysio_boot(const char *buf);
+
+/*
+ * SYSIO name label macros
+ */
+#define XPREPEND(p,x) p ## x
+#define PREPEND(p,x) XPREPEND(p,x)
+#define SYSIO_LABEL_NAMES 0
+#if SYSIO_LABEL_NAMES
+#define SYSIO_INTERFACE_NAME(x) PREPEND(sysio__, x)
+#else
+#define SYSIO_INTERFACE_NAME(x) x
+#endif
+
+/*
+ * The following should be defined by the system includes, and probably are,
+ * but it's not illegal to have multiple externs, so long as they are the
+ * same. It helps when building the library in a standalone fashion.
+ */
+extern int SYSIO_INTERFACE_NAME(access)(const char *path, int amode);
+extern int SYSIO_INTERFACE_NAME(chdir)(const char *path);
+extern int SYSIO_INTERFACE_NAME(chmod)(const char *path, mode_t mode);
+extern int SYSIO_INTERFACE_NAME(fchmod)(int fd, mode_t mode);
+extern int SYSIO_INTERFACE_NAME(chown)(const char *path, uid_t owner,
+                                      gid_t group);
+extern int SYSIO_INTERFACE_NAME(fchown)(int fd, uid_t owner, gid_t group);
+extern int SYSIO_INTERFACE_NAME(close)(int d);
+extern int SYSIO_INTERFACE_NAME(dup)(int oldfd);
+extern int SYSIO_INTERFACE_NAME(dup2)(int oldfd, int newfd);
+extern int SYSIO_INTERFACE_NAME(fcntl)(int fd, int cmd, ...);
+extern int SYSIO_INTERFACE_NAME(fstat)(int fd, struct stat *buf);
+extern int SYSIO_INTERFACE_NAME(fsync)(int fd);
+extern char *SYSIO_INTERFACE_NAME(getcwd)(char *buf, size_t size);
+extern off_t SYSIO_INTERFACE_NAME(lseek)(int fd, off_t offset, int whence);
+#if _LARGEFILE64_SOURCE
+extern off64_t SYSIO_INTERFACE_NAME(lseek64)(int fd, off64_t offset, 
+                                            int whence);
+#endif
+extern int SYSIO_INTERFACE_NAME(lstat)(const char *path, struct stat *buf);
+#ifdef BSD
+extern int SYSIO_INTERFACE_NAME(getdirentries)(int fd, char *buf, int nbytes , 
+                                              long *basep);
+#else
+extern ssize_t SYSIO_INTERFACE_NAME(getdirentries)(int fd, char *buf, 
+                                                  size_t nbytes, off_t *basep);
+#if _LARGEFILE64_SOURCE
+extern ssize_t SYSIO_INTERFACE_NAME(getdirentries64)(int fd,
+                                                    char *buf,
+                                                    size_t nbytes,
+                                                    off64_t *basep);
+#endif
+#endif
+extern int SYSIO_INTERFACE_NAME(mkdir)(const char *path, mode_t mode);
+extern int SYSIO_INTERFACE_NAME(open)(const char *path, int flag, ...);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(open64)(const char *path, int flag, ...);
+#endif
+extern int SYSIO_INTERFACE_NAME(creat)(const char *path, mode_t mode);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(creat64)(const char *path, mode_t mode);
+#endif
+extern int SYSIO_INTERFACE_NAME(stat)(const char *path, struct stat *buf);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(stat64)(const char *path, struct stat64 *buf);
+#endif
+#ifdef _HAVE_STATVFS
+extern int SYSIO_INTERFACE_NAME(statvfs)(const char *path, struct statvfs *buf);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(statvfs64)(const char *path, 
+                               struct statvfs64 *buf);
+#endif
+extern int SYSIO_INTERFACE_NAME(fstatvfs)(int fd, struct statvfs *buf);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(fstatvfs64)(int fd, struct statvfs64 *buf);
+#endif
+#endif
+extern int SYSIO_INTERFACE_NAME(truncate)(const char *path, off_t length);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(truncate64)(const char *path, off64_t length);
+#endif
+extern int SYSIO_INTERFACE_NAME(ftruncate)(int fd, off_t length);
+#if _LARGEFILE64_SOURCE
+extern int SYSIO_INTERFACE_NAME(ftruncate64)(int fd, off64_t length);
+#endif
+extern int SYSIO_INTERFACE_NAME(rmdir)(const char *path);
+extern int SYSIO_INTERFACE_NAME(symlink)(const char *path1, const char *path2);
+extern int SYSIO_INTERFACE_NAME(readlink)(const char *path,
+                               char *buf,
+                               size_t bufsiz);
+extern int SYSIO_INTERFACE_NAME(link)(const char *oldpath, const char *newpath);
+extern int SYSIO_INTERFACE_NAME(unlink)(const char *path);
+extern int SYSIO_INTERFACE_NAME(rename)(const char *oldpath, 
+                                       const char *newpath);
+extern int SYSIO_INTERFACE_NAME(fdatasync)(int fd);
+extern int SYSIO_INTERFACE_NAME(ioctl)(int fd, unsigned long request, ...);
+extern mode_t SYSIO_INTERFACE_NAME(umask)(mode_t mask);
+extern int SYSIO_INTERFACE_NAME(iodone)(ioid_t ioid);
+extern ssize_t SYSIO_INTERFACE_NAME(iowait)(ioid_t ioid);
+extern ioid_t SYSIO_INTERFACE_NAME(ipreadv)(int fd, const struct iovec *iov, 
+                                  size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ioid_t SYSIO_INTERFACE_NAME(ipread64v)(int fd, const struct iovec *iov, 
+                                             size_t count, off64_t offset);
+#endif
+extern ioid_t SYSIO_INTERFACE_NAME(ipread)(int fd, void *buf, size_t count, 
+                                          off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ioid_t SYSIO_INTERFACE_NAME(ipread64)(int fd, void *buf, size_t count, 
+                                            off64_t offset);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(preadv)(int fd, const struct iovec *iov, 
+                                           size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ssize_t SYSIO_INTERFACE_NAME(pread64v)(int fd, const struct iovec *iov, 
+                                             size_t count, off64_t offset);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(pread)(int fd, void *buf, size_t count, 
+                                          off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ssize_t SYSIO_INTERFACE_NAME(pread64)(int fd, void *buf, size_t count, 
+                                            off64_t offset);
+#endif
+extern ioid_t SYSIO_INTERFACE_NAME(ireadv)(int fd, const struct iovec *iov, 
+                                          int count);
+extern ioid_t SYSIO_INTERFACE_NAME(iread)(int fd, void *buf, size_t count);
+extern ssize_t SYSIO_INTERFACE_NAME(readv)(int fd, const struct iovec *iov, 
+                                          int count);
+extern ssize_t SYSIO_INTERFACE_NAME(read)(int fd, void *buf, size_t count);
+extern ioid_t SYSIO_INTERFACE_NAME(ipwritev)(int fd, const struct iovec *iov, 
+                                            size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ioid_t SYSIO_INTERFACE_NAME(ipwrite64v)(int fd, const struct iovec *iov, 
+                                              size_t count, off64_t offset);
+#endif
+extern ioid_t SYSIO_INTERFACE_NAME(ipwrite)(int fd, const void *buf, 
+                                           size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ioid_t SYSIO_INTERFACE_NAME(ipwrite64)(int fd, const void *buf, 
+                                             size_t count, off64_t offset);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(pwritev)(int fd, const struct iovec *iov, 
+                                            size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ssize_t SYSIO_INTERFACE_NAME(pwrite64v)(int fd, const struct iovec *iov, 
+                                              size_t count, off64_t offset);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(pwrite)(int fd, const void *buf, 
+                                           size_t count, off_t offset);
+#if _LARGEFILE64_SOURCE
+extern ssize_t SYSIO_INTERFACE_NAME(pwrite64)(int fd, const void *buf, 
+                                             size_t count, off64_t offset);
+#endif
+extern ioid_t SYSIO_INTERFACE_NAME(iwritev)(int fd, 
+                                           const struct iovec *iov, 
+                                           int count);
+extern ioid_t SYSIO_INTERFACE_NAME(iwrite)(int fd, const void *buf, 
+                                          size_t count);
+extern ssize_t SYSIO_INTERFACE_NAME(writev)(int fd, const struct iovec *iov, 
+                                           int count);
+extern ssize_t SYSIO_INTERFACE_NAME(write)(int fd, const void *buf, 
+                                          size_t count);
+extern int SYSIO_INTERFACE_NAME(mknod)(const char *path, 
+                                      mode_t mode, dev_t dev);
+extern int SYSIO_INTERFACE_NAME(utime)(const char *path, 
+                                      const struct utimbuf *buf);
+extern int SYSIO_INTERFACE_NAME(mount)(const char *source, const char *target,
+                                      const char *filesystemtype,
+                                      unsigned long mountflags,
+                                      const void *data);
+extern int SYSIO_INTERFACE_NAME(umount)(const char *target);
+
+/* for debugging */
+#if 0
+#define ASSERT(cond)                                                   \
+       if (!(cond)) {                                                  \
+               printf("ASSERTION(" #cond ") failed: " __FILE__ ":"     \
+                       __FUNCTION__ ":%d\n", __LINE__);                \
+               abort();                                                \
+       }
+
+#define ERROR(fmt, a...)                                               \
+       do {                                                            \
+               printf("ERROR(" __FILE__ ":%d):" fmt, __LINE__, ##a);   \
+       while(0)
+
+#else
+#define ERROR(fmt)     do{}while(0)
+#define ASSERT         do{}while(0)
+#endif
+
+/*
+ * SYSIO interface frame macros
+ *
+ * + DISPLAY_BLOCK; Allocates storage on the stack for use by the set of
+ *     macros.
+ * + ENTER; Performs entry point work
+ * + RETURN; Returns a value and performs exit point work
+ *
+ * NB: For RETURN, the arguments are the return value and value for errno.
+ * If the value for errno is non-zero then that value, *negated*, is set
+ * into errno.
+ */
+#define SYSIO_INTERFACE_DISPLAY_BLOCK \
+       int _saved_errno;
+#define SYSIO_INTERFACE_ENTER \
+       do { \
+               _saved_errno = errno; \
+               SYSIO_ENTER; \
+       } while (0)
+#define SYSIO_INTERFACE_RETURN(rtn, err) \
+       do { \
+               SYSIO_LEAVE; \
+               errno = (err) ? -(err) : _saved_errno; \
+               return (rtn); \
+       } while(0) 
+
+/* syscall enter/leave hook functions  */
+#if 0
+extern void _sysio_sysenter();
+extern void _sysio_sysleave();
+
+#define SYSIO_ENTER                                                    \
+       do {                                                            \
+               _sysio_sysenter();                                      \
+       } while(0)
+
+#define SYSIO_LEAVE                                                    \
+       do {                                                            \
+               _sysio_sysleave();                                      \
+       } while(0)
+#else
+#define SYSIO_ENTER
+#define SYSIO_LEAVE
+
+#endif
diff --git a/libsysio/include/xtio.h b/libsysio/include/xtio.h
new file mode 100644 (file)
index 0000000..765aaf8
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2004 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+/*
+ * Structure for strided I/O.
+ */
+struct xtvec {
+#ifndef __USE_FILE_OFFSET64
+       __off_t xtv_off;                        /* Stride/Extent offset. */
+#else
+       __off64_t xtv_off;                      /* Stride/Extent offset. */
+#endif
+       size_t  xtv_len;                        /* Stride/Extent length. */
+};
+
+#ifdef __USE_LARGEFILE64
+struct xtvec64 {
+       __off64_t xtv_off;                      /* Stride/Extent offset. */
+       size_t  xtv_len;                        /* Stride/Extent length. */
+};
+#endif
+
+extern ioid_t SYSIO_INTERFACE_NAME(ireadx)(int fd,
+                                          const struct iovec *iov, 
+                                          size_t iov_count,
+                                          const struct xtvec *xtv, 
+                                          size_t xtv_count);
+#ifdef __USE_LARGEFILE64
+extern ioid_t SYSIO_INTERFACE_NAME(iread64x)(int fd,
+                                            const struct iovec *iov, 
+                                            size_t iov_count,
+                                            const struct xtvec64 *xtv, 
+                                            size_t xtv_count);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(readx)(int fd,
+                                          const struct iovec *iov, 
+                                          size_t iov_count,
+                                          const struct xtvec *xtv, 
+                                          size_t xtv_count);
+#ifdef __USE_LARGEFILE64
+extern ssize_t SYSIO_INTERFACE_NAME(read64x)(int fd,
+                                            const struct iovec *iov, 
+                                            size_t iov_count,
+                                            const struct xtvec64 *xtv, 
+                                            size_t xtv_count);
+#endif
+extern ioid_t SYSIO_INTERFACE_NAME(iwritex)(int fd,
+                                           const struct iovec *iov, 
+                                           size_t iov_count,
+                                           const struct xtvec *xtv, 
+                                           size_t xtv_count);
+#ifdef __USE_LARGEFILE64
+extern ioid_t SYSIO_INTERFACE_NAME(iwrite64x)(int fd,
+                                             const struct iovec *iov, 
+                                             size_t iov_count,
+                                             const struct xtvec64 *xtv, 
+                                             size_t xtv_count);
+#endif
+extern ssize_t SYSIO_INTERFACE_NAME(writex)(int fd,
+                                           const struct iovec *iov, 
+                                           size_t iov_count,
+                                           const struct xtvec *xtv, 
+                                           size_t xtv_count);
+#ifdef __USE_LARGEFILE64
+extern ssize_t SYSIO_INTERFACE_NAME(write64x)(int fd,
+                                             const struct iovec *iov, 
+                                             size_t iov_count,
+                                             const struct xtvec64 *xtv, 
+                                             size_t xtv_count);
+#endif
diff --git a/libsysio/misc/gdb-libsysio b/libsysio/misc/gdb-libsysio
new file mode 100644 (file)
index 0000000..dd3f613
--- /dev/null
@@ -0,0 +1,127 @@
+#    This Cplant(TM) source code is the property of Sandia National
+#    Laboratories.
+#
+#    This Cplant(TM) source code is copyrighted by Sandia National
+#    Laboratories.
+#
+#    The redistribution of this Cplant(TM) source code is subject to the
+#    terms of the GNU Lesser General Public License
+#    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+#
+#    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+#    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+#    license for use of this work by or on behalf of the US Government.
+#    Export of this program may require a license from the United States
+#    Government.
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Questions or comments about this library should be sent to:
+#
+# Lee Ward
+# Sandia National Laboratories, New Mexico
+# P.O. Box 5800
+# Albuquerque, NM 87185-1110
+#
+# lee@sandia.gov
+
+#
+# Useful commands for debugging libsysio in gdb
+#
+
+define x_dump_pbnode
+       printf "%p: ", $arg0
+       if $arg0->pb_name.name
+               printf " \"%s\"", \
+                 $arg0->pb_name.name
+       else
+               printf " <NULL>"
+       end
+       printf " aliases:["
+       set $x_p = $arg0->pb_aliases.lh_first
+       while $x_p
+               printf "<%p r:%d mnt:%p>", \
+                 $x_p, \
+                 $x_p->p_ref, \
+                 $x_p->p_mount
+               set $x_p = $x_p->p_links.le_next
+       end
+       printf "]\n"
+end
+document x_dump_pbnode
+Dump path-base node and it's aliases
+
+Usage: x_dump_pbnode <pbnode>
+end
+
+define __x_dump_pnode
+       printf "%spnode %p, mount %p, base: ", $arg0, $arg1, $arg1->p_mount
+       x_dump_pbnode $arg1->p_base
+end
+
+define x_dump_pnode
+       __x_dump_pnode "" $arg0
+end
+document x_dump_pnode
+Dump path node information
+
+Usage: x_dump_pnode <pnode>
+end
+
+define x_dump_mount
+       printf "MOUNT %p: root pnode %p, covers %p\n", \
+           $arg0, $arg0->mnt_root, $arg0->mnt_covers
+       set $_x_dump_mount_var_pno = _sysio_pnodes->tqh_first
+       while $_x_dump_mount_var_pno != 0
+printf "%p, %p\n", $_x_dump_mount_var_pno, $arg0
+               if $_x_dump_mount_var_pno->p_mount == $arg0
+                       __x_dump_pnode " " $_x_dump_mount_var_pno
+               end
+               set $_x_dump_mount_var_pno = \
+                   $_x_dump_mount_var_pno->p_nodes.tqe_next
+       end
+end
+document x_dump_mount
+Dump single mount record information
+
+Usage: x_dump_mount <mnt>
+end
+
+define x_dump_mounts
+       set $__x_dump_mounts_var_mnt = mounts.lh_first
+       while $__x_dump_mounts_var_mnt
+               x_dump_mount $__x_dump_mounts_var_mnt
+               set $__x_dump_mounts_var_mnt = \
+                   $__x_dump_mounts_var_mnt->mnt_link.le_next
+       end
+end
+document x_dump_mounts
+Dump the contents of the libsysio mount table
+
+Usage: x_dump_mounts
+end
+
+define x_dump_pnodes
+       set $_x_dump_pnodes_var_pno = _sysio_pnodes.tqh_first
+       while $_x_dump_pnodes_var_pno
+               x_dump_pnode $_x_dump_pnodes_var_pno
+               set $_x_dump_pnodes_var_pno = \
+                   $_x_dump_pnodes_var_pno->p_nodes.tqe_next
+       end
+end
+
+br _sysio_unmount_all
+run -r /tmp/lee foo bar
+x_dump_pnodes
diff --git a/libsysio/misc/init-env.sh b/libsysio/misc/init-env.sh
new file mode 100644 (file)
index 0000000..167f421
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Source this file. It will craft a usable name space for your testing.
+#
+# Lee; Sun Feb  8 18:02:16 EST 2004
+#
+# Note: We really should support symlinks someday.
+#
+unset _root_flags
+unset _extras
+if [ "x${SYSIO_AUTOMOUNT}" == "xyes" ]; then
+       _root_flags="2"
+       #
+       # Add a /auto directory for automounted file systems. We
+       # craft one automount that mounts /usr/home from the native
+       # file system. Further automounts in the sub-mounts are not enabled.
+       #
+       _extras=" \
+               {mnt,   dev=\"incore:0755+0+0\",dir=\"/mnt\",fl=2} \
+               {creat, ft=dir,nm=\"/mnt/home\",pm=04755,ow=0,gr=0} \
+               {creat, ft=file,nm=\"/mnt/home/.mount\",pm=0600, \
+                       str=\"native:/home\"} \
+       "
+fi
+export SYSIO_NAMESPACE="\
+       {mnt,   dev=\"native:/\",dir=/,fl=${_root_flags:-0}} \
+       {mnt,   dev=\"incore:0755+0+0\",dir=\"/dev\"} \
+       {creat, ft=chr,nm=\"/dev/stdin\",pm=0400,mm=0+0} \
+       {creat, ft=chr,nm=\"/dev/stdout\",pm=0200,mm=0+1} \
+       {creat, ft=chr,nm=\"/dev/stderr\",pm=0200,mm=0+2} \
+       {creat, ft=dir,nm=\"/dev/fd\",pm=0755,ow=0,gr=0} \
+       {creat, ft=chr,nm=\"/dev/fd/0\",pm=0400,mm=0+0} \
+       {creat, ft=chr,nm=\"/dev/fd/1\",pm=0200,mm=0+1} \
+       {creat, ft=chr,nm=\"/dev/fd/2\",pm=0200,mm=0+2} \
+       {cd,    dir=\"$HOME\"} \
+       ${_extras} \
+"
+unset _root_flags
+unset _extras
diff --git a/libsysio/src/access.c b/libsysio/src/access.c
new file mode 100644 (file)
index 0000000..e2f6211
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *    This Cplant(TM) source code is the property of Sandia National
+ *    Laboratories.
+ *
+ *    This Cplant(TM) source code is copyrighted by Sandia National
+ *    Laboratories.
+ *
+ *    The redistribution of this Cplant(TM) source code is subject to the
+ *    terms of the GNU Lesser General Public License
+ *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
+ *
+ *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
+ *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+ *    license for use of this work by or on behalf of the US Government.
+ *    Export of this program may require a license from the United States
+ *    Government.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Questions or comments about this library should be sent to:
+ *
+ * Lee Ward
+ * Sandia National Laboratories, New Mexico
+ * P.O. Box 5800
+ * Albuquerque, NM 87185-1110
+ *
+ * lee@sandia.gov
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "sysio-symbols.h"
+#include "sysio.h"
+
+int
+SYSIO_INTERFACE_NAME(access)(const char *path, int amode)
+{
+       gid_t   *list, *entry;
+       size_t  n;
+       int     err = 0;
+       unsigned mask, mode;
+       struct stat stbuf;
+       SYSIO_INTERFACE_DISPLAY_BLOCK;
+
+       SYSIO_INTERFACE_ENTER;
+       err = 0;
+
+       n = getgroups(0, NULL);
+       list = NULL;
+       if (n) {
+               list = malloc(n * sizeof(gid_t));
+               if (!list) {
+                       err = -ENOMEM;
+                       goto out;
+&