--- /dev/null
+Lee Ward <lee@sandia.gov>
--- /dev/null
+ 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!
--- /dev/null
+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.
--- /dev/null
+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:
--- /dev/null
+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
--- /dev/null
+
+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
--- /dev/null
+#!/bin/sh
+
+aclocal &&
+automake --add-missing --copy &&
+${AUTOCONF:-autoconf}
--- /dev/null
+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)
+
--- /dev/null
+STDFD_SRCS = dev/stdfd/stdfd.c
+STDFD_EXTRA = dev/stdfd/stdfd.h dev/stdfd/module.mk
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+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.
--- /dev/null
+/*
+ * 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,
+ ©_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);
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+INCORE_SRCS = drivers/incore/fs_incore.c
+INCORE_EXTRA = drivers/incore/fs_incore.h drivers/incore/module.mk
--- /dev/null
+/*
+ * 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.
+ */
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+NATIVE_SRCS = drivers/native/fs_native.c
+NATIVE_EXTRA = drivers/native/fs_native.h drivers/native/module.mk
--- /dev/null
+SOCKETS_SRCS = drivers/sockets/sockets.c
+SOCKETS_EXTRA = drivers/sockets/module.mk
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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.
+ */
+}
--- /dev/null
+/*
+ * 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();
--- /dev/null
+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
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
--- /dev/null
+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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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;
+&